python中一切都是对象,参数传递都是对象的引用,具体的,如果函数收到的是可变对象(如列表字典),则可以修改对象的原始值;如果是不可变对象(整型浮点型字符元组),就不能修改原始对象。
首先看可变对象的赋值:
>>> a = [1, 2, 3]
>>> b = a
>>> b.append(4)
>>> print a, b
[1, 2, 3, 4] [1, 2, 3, 4]
执行a = [1, 2, 3]后,a指向这个列表,执行b = a后,b也指向这个列表,两个变量指向同一块内存,因此对b的操作也会影响a。
再看不可变对象的赋值:
>>> a = 1
>>> b = a
>>> a = 2
>>> print a,b
2 1
执行a=1后开辟了一块内存存放1,然后b也指向1,执行a=2后,因为整型不可变,所以又开辟了一块内存存放2,现在a指向2,b还指向1。
通过下面这个例子再感受一下可变和不可变对象:
>>>a = 1
>>>b = 1
>>>a is b
True
>>>a = [1,2]
>>>b = [1,2]
>>>a is b
False
然后看浅复制copy():
>>>a = [1,2,[3,4]]
>>>b = a.copy()
>>>b.append(5)
>>>print b
[1,2,[3,4],5]
>>>print a
[1,2,[3,4]]
此时原列表a不受影响,再接着看:
>>>b[2].append(5)
>>>print b
[1,2,[3,4,5],5]
>>>print a
[1,2,[3,4,5]]
可以看到a和b都改变了,也就是说copy()方法返回一个和原对象不同的新对象,但是把原对象中的引用也复制到新对象中。不可变类型不受此影响,但如本例中的列表内的子列表,属于可变数据类型,修改它便会影响原列表。
最后看深复制deepcopy():
>>>from copy import deepcopy
>>>a = [1,2,[3,4]]
>>>b = deepcopy(a)
>>>b[2].append(5)
>>>print b
[1,2,[3,4,5]]
>>>print a
[1,2,[3,4]]
深复制会对原列表中的元素进行递归,会把嵌套的子列表的值也复制过来,而不是只复制引用,虽然多花费了一些时间和空间,但是新列表和原列表是互相独立的,互不影响。