python的拷贝
笔记整理自:
- https://my.oschina.net/leejun2005/blog/145911
- https://zhuanlan.zhihu.com/p/25221086
https://docs.python.org/3/library/copy.html
4.https://zhuanlan.zhihu.com/p/54011712
(强烈推荐看最后一个)赋值操作
只是复制了新对象的引用,不会开辟新的内存空间。
python的赋值语句是建立对象的引用而不是复制对象,创建的是局部变量,例如:list_a = [] def a(): list_a = [1] ## 语句1 a()
在函数中赋值并不会改变全局变量的值,输出值为[]
values = [0, 1, 2] values[1] = values
此时values的值为[0, [...], 2],其中values[1]是无限循环的值,因为创建了自身的引用。
正确的做法应当是:values[1] = values[:]
list的[:]操作其实是浅拷贝。
浅拷贝与深拷贝
浅拷贝:A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.创建新对象,其内容是原对象的引用。有三种浅拷贝的形式:切片操作,工厂函数,copy操作
浅复制要分两种情况进行讨论:
1)当浅复制的值是不可变对象(字符串、元组、数值类型)时和“赋值”的情况一样,对象的id值(id()函数用于获取对象的内存地址)与浅复制原来的值相同。
2)当浅复制的值是可变对象(列表、字典、集合)时会产生一个“不是那么独立的对象”存在。有两种情况:
第一种情况:复制的对象中无复杂子对象,原来值的改变并不会影响浅复制的值,同时浅复制的值改变也并不会影响原来的值。原来值的id值与浅复制原来的值不同。
第二种情况:复制的对象中有复杂子对象(例如列表中的一个子元素是一个列表),如果不改变其中复杂子对象,浅复制的值改变并不会影响原来的值。 但是改变原来的值中的复杂子对象的值会影响浅复制的值。
深拷贝:A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.
不可变对象类型,没有被拷贝的说法,即便是用深拷贝,查看id的话也是一样的,如果对其重新赋值,也只是新创建一个对象,替换掉旧的而已。
Python的可变与不可变对象
不可变对象:int, float, long, str, tuple
可变对象:list, set, dict等
>>> a = 'xianglong.me'
>>> id(a)
140443303134352
>>> a = '1saying.com'
>>> id(a)
140443303131776
def func_int(a):
a += 4
t = 0
func_int(t)
print t
# output: 0
对于不可变对象,每一次操作都会创建一个新值,把变量绑定到新的对象上,旧的值没有被引用就等待垃圾回收。a是t的对象的新引用,修改不可变对象后,a会指向新的对象,但是不会改变旧的对象,所以t不变。但是如果传入的是可变对象的引用,就可以更改对象的值。
>>> a_list = [1, 2, 3]
>>> id(a_list)
140443302951680
>>> a_list.append(4)
>>> id(a_list)
140443302951680
对于可变对象,操作不会改变地址。