零:
先看几个代码
>>> a=10000
>>> b=10000
>>> a is b
False
>>> c=a
>>> c is a
True
>>> id(a)
140620919220456
>>> id(b)
140620919220432
>>> id(c)
140620919220456
这里的a和b,虽然都是同样的值1000 但他们并不是同一个东西,所以a is b 是 False。从代码层面讲,这里是因为 在定义a=10000的时候,计算机在140620919220456的地方开辟了一段内存,存为值10000,然后再给这段内存值 取了个名字叫a 。 定义b=10000的时候 计算机又在140620919220432的地方存了一个10000 取名字叫b 这俩货都不在同一个地方,只是凑巧值一样罢了,所以 a is b当然False 了 当执行 c = a 的时候,计算机只是给给140620919220456这段内存取了个别名,叫c而已。别忘了这段内存以前还有个名字叫a。既然是同一个东西 只是名字不同 那 c is a 当然True了
所以这里的 a b c与其叫变量名称 不如叫指针更合适 比如a指向的地址为内存140620919220456的值。
一:
看一个常见的错误例题
def fun(a=[]):
a.append(1)
print(a)
调用这个函数两次 我们会看到
>>> fun()
[1]
>>> fun()
[1, 1]
如果把参数a的默认参数换为字典呢?
def fun(a={}):
import random
key = random.randint(1, 100)
a[key] = 1
print(a)
>>> fun()
{46: 1}
>>> fun()
{74: 1, 46: 1}
>>>
怎么从原理来解释这件事情呢?当函数初始化的时候 并不是分配了一个空的list 或者空的dict给函数 而是给a的一个list或者dict的地址。在运行的时候,直接在这个地址指向的地方,开始操作。我们把参数的ID打出来看一看
>>> def fun(a=[]):
... a.append(1)
... print(a)
... print(id(a))
...
>>> fun()
[1]
4501980800
>>> fun()
[1, 1]
4501980800
>>>
我们可以看到 id并没有变 如果你学过C语言那么你应该一下就明白这里是指针的意思。
所以我们一定要理解到,这里参数传进去的,只是一个指针,只是一个地址,并不是一个实实在在的数据结构段。
二:
函数都有返回值,比如return 0 return "ok"等 如果一个函数没有刻意的写明return 那么默认return None 这个在初学python的时候就讲过,那么除了 int str 等类型,还有哪些可以作为return的值呢?函数可以不可以呢?
# 定义一个函数 不管接受到什么参数 直接返回接受到的东西
def return_fun(a):
return a
>>> return_fun(1)
1
>>> return_fun('aaaa')
'aaaa'
>>>
# 再定义一个加法函数
def add(a, b):
return a + b
>>> add(1,2)
3
# 执行下面的代码
>>> new = return_fun(add)
>>> new
<function add at 0x10b9351b8>
>>> add
<function add at 0x10b9351b8>
>>> new(1,2)
3
看到没 new 和 add 是完全一样的东西,也就是说 return_fun 接受了一个add 函数 然后又返回了这个函数 然后把这个函数赋值给了new 也就是说 现在new 这个变量 和add指向的是同一块代码区域 都是0x10b9351b8
想一下 为什么能return 一个函数呢? 其实啊 return "aaaa"
并不是return了字符串”aaaa“
本身, 而是return的一个地址 那个地址里存的是一窜"aaaa"字符串而已。弄懂了这个,也就不难理解为什么能return一个函数,因为其实return的并不是函数本身,而是return一个指向那段函数代码的一个指针而已,上面代码中,new就是那个指针,new后面加个括号new(1, 2) 就是执行new指向的代码段。
网友评论