Python基本类型分类
可变类型:List、Dict、Set。在保持地址固定的情况下可改变取值
不可变类型:Number、String、Tuple。改变值的情况下必须新建一个对象。
结论:Python存储的数据类型中,指挥存储基本类型的数据,如不可变类型。如果需要重新存储已存在的对象,则使用引用的方式,指向原来的值。
Python中的集中复制方式
赋值
当给一个变量赋值时,其实就是将对象的引用复制了一份给 a 和 b ,可以看到数字 5 原本的地址就是140716710627120
,不管赋给哪个变量,地址都是同一个,也就是指向同一个对象。
1 2 3 4 5 6 7 8 9
| >>> a=5 >>> b=a >>> id(a) 140716710627120 >>> id(b) 140716710627120 >>> id(5) 140716710627120 >>>
|
浅拷贝
可以看到这里的 cd 和之前的 ad 地址不同,因为开启了新的内存空间。就算去修改 cd 的值,不会影响 ad 。但仅限于 cd 和 ad 两个对象,其各自的子对象还是指向同一个对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| >>> ad = {"name":"qiwsir", "lang":"python"} >>> cd = ad.copy() >>> cd {'name': 'qiwsir', 'lang': 'python'} >>> id(ad) 2191309359104 >>> id(cd) 2191309359168 >>> >>> cd['name']='baidu' >>> cd {'name': 'baidu', 'lang': 'python'} >>> ad {'name': 'qiwsir', 'lang': 'python'} >>> >>> id(ad['name']) 2191309705072 >>> id(cd['name']) 2191309705072 >>>
|
然而,如果需要完全赋值一份真正的“副本”,浅拷贝是不能完成任务的。
1 2 3 4 5 6 7
| >>> x = {"name":"qiwsir", "lang":["python", "java", "c"]} >>> y = x.copy() >>> id(x) 2191309704384 >>> id(y) 2191309416128 >>>
|
在 x 这个字典中,有 2 个键值对。一个是字符串name
,一个是列表lang
。通过copy()得到了两个不同地址的对象。
将 y 中列表其中一个值删除。你会发现连 x 中列表的值也发生了改变。
1 2 3 4 5 6
| >>> y['lang'].remove('c') >>> y {'name': 'qiwsir', 'lang': ['python', 'java']} >>> x {'name': 'qiwsir', 'lang': ['python', 'java']} >>>
|
如果一个变量的值修改了,另一个变量也跟着改变,那么它们很可能是同一个地址,因此用id()看一下,果然是。
1 2 3 4 5
| >>> id(x['lang']) 2191309704128 >>> id(y['lang']) 2191309704128 >>>
|
如果修改各自字典中的字符串,那么二者互不影响
1 2 3 4 5 6
| >>> x['name']='baidu' >>> x {'name': 'baidu', 'lang': ['python', 'java']} >>> y {'name': 'qiwsir', 'lang': ['python', 'java']} >>>
|
深拷贝
使用copy模块下的 deepcopy() 函数来实现深拷贝。
1 2 3 4 5 6 7 8 9 10 11 12
| >>> import copy >>> z = copy.deepcopy(x) >>> z {'name': 'baidu', 'lang': ['python', 'java']} >>> x {'name': 'baidu', 'lang': ['python', 'java']} >>> z['lang'].append('javascript') >>> z {'name': 'baidu', 'lang': ['python', 'java', 'javascript']} >>> x {'name': 'baidu', 'lang': ['python', 'java']} >>>
|
Python官方文档有对此说明:https://docs.python.org/3/library/copy.html
这里说到,浅拷贝和深拷贝的区别仅与符合对象有关:
- 浅拷贝在复制复合对象时,在尽可能的范围内寻找被复制对象的对象的引用插入其中
- 深拷贝在复制复合对象时,递归地将被复制对象的副本插入其中。