赋值
1 >>> a=[1,2,[3,4]]
2 >>> b=a
3 >>> c=a 4 >>> a is b 5 True 6 >>> c is a 7 True
赋值完还是同一个对象,地址内容完全一样
切片
1 >>> a=[1,2,[3,4]]
2 >>> b=a[:]
3 >>> b is a 4 False 5 >>> id(a),id(b) 6 (2192816216904, 2192816215240) 7 >>> id(a[2]),id(b[2]) 8 (2192816228424, 2192816228424) 9 >>>
切片是不同的两个对象,只是对内容的引用,因此内容的地址是一样的 工厂函数
1 >>> a=[1,2,[3,4]]
2 >>> c=list(a)
3 >>> a is c 4 False 5 >>> id(a),id(c) 6 (2192816252616, 2192816268424) 7 >>> id(a[2]),id(c[2]) 8 (2192816259784, 2192816259784)
浅复制
1 >>> import copy
2 >>> a=[1,2,[3,4]]
3 >>> b=a.copy() 4 >>> b is a 5 False 6 >>> id(a),id(b) 7 (2192816286728, 2192816270152) 8 >>> id(a[2]),id(b[2]) 9 (2192816284168, 2192816284168)
因此,切片,工厂函数,浅复制的作用相同 深复制
1 >>> a=[1,2,[3,4]]
2 >>> b=copy.deepcopy(a)
3 >>> [id(x) for x in [a,b]] 4 [2192815840328, 2192816284424] 5 >>> [id(x) for x in a] 6 [1593201440, 1593201472, 2192805444360] 7 >>> [id(x) for x in b] 8 [1593201440, 1593201472, 2192805417288]
可见,深复制已经不是对内容的引用了。深复制前后两个对象是完全不同的,不再是简单的引用了,需要注意前两个元素地址相同,第三个地址不同
下面对比下赋值,与切片(工厂函数,浅复制)
赋值:完全相同的两个对象,单个改变里面的对象,两个全变。但是当整体改变a时,相当于a已经换了引用的对象,b保持不变
1 >>> a=[1,2,[3,4]]
2 >>> b=a
3 >>> a[0],a[1],a[2]=3,4,5
4 >>> b 5 [3, 4, 5] 6 >>> a=[4,5,6] 7 >>> b 8 [3, 4, 5]
切片:使用切片两个对象是不相同的,首先分析改变列表里面不可变元素,序列化元素放到深浅复制里面分析
a,b 两个对象是不同的,但是里面的内容,以及内容的地址时相同的。
这个情况与赋值不同。
为什么会出现这种情况呢?
图片参考:http://python.jobbole.com/82294/
浅复制创建了一个新的对象b,但是由于懒惰,只使用了原始元素的内存地址。
a中的第一个元素是不可变对象,所以重新赋值的使用了新的地址,但是b这个不同的对象,依然指向原始地址。
对于a中第三个元素,是一个列表,我们改变的是里面的元素。由上面改变a[1]可以看到,a的地址并没有改变,而我们引用的是
第三个元素的地址,所以改变a[2]或b[2],a,b会一起变
深复制
由上面的深复制可以看出,当列表中存在列表,使用深复制时,地址是不相同的。所以你改变a,b肯定不变啊。
最重要的问题:深复制,切片,工厂函数等 a,b,的前两个元素地址时一样的。为什么呢:非容器类型(比如数字,字符串和其他"原子"类型的)没有被拷贝一说,只是对其
进行引用,只要修改,就会产生新的对象。(难以理解)