看两个例子:
### 1⃣️ a = 1 def fun(a): a = 2 fun(a) print a # 1 ### 2⃣️ a = [] def fun(a): a.append(1) fun(a) print a # [1]
所有的变量都可以理解是内存中的一个对象的“引用”,或者,也可以看似void*的感觉。
通过id来查看引用a的内存地址可以比较好理解
a = 1 def fun(a): print ("func_in",id(a)) # func_in 4372249088 a = 2 print ("re-point",id(a), id(2)) # re-point 4372249120 4372249120 print ("func_out",id(a), id(1)) # func_out 4372249088 4372249088 fun(a) print (a) # 1
注:具体的值在不同电脑上运行时可能不同
可以看到,在执行完a=2之后,a引用中保存的值,即内存地址发生变化,由原来1对象的所在的地址变成2这个实体对象的内存地址。
而第2个例子a引用保存的内存值就不会发生变化:
a = [] def fun(a): print ("func_in",id(a)) # func_in 140198448542336 a.append(1) print ("func_out",id(a)) # func_out 140198448542336 fun(a) print (a) # [1]
这里记住的是类型是属于对象的,而不是变量。而对象有两种,“可更改”(mutable)与不可更改(immutable)对象。在python中,strings,tuples,和numbers是不可更改的对象,而list,dict,set等是可以修改的对。(这就是这个问题的重点)
当一个引用传递给函数的时候,函数自动复制一份引用,这个函数里的引用和外面的引用没有半毛钱关系了,所以第一个例子里函数把引用只想了一个不可变对象,当函数返回的时候,外面的引用不会改变。而第二个例子酒不一样了,函数内的引用指向的是可变对象,对它的操作就喝定位了指针地址一样,在内存里进行修改。
如果还不明白的话,这里有更好的解释:
http://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference
评论