首页 > 编程 > Python > 正文

python中的深拷贝和浅拷贝(读书笔记)

2019-11-06 06:13:45
字体:
来源:转载
供稿:网友
python中,对象赋值实际上是简单的对象引用,也就是说当你创建一个对象,然后把它赋值给另一个变量的时候,python并没有拷贝这个对象,而是拷贝了这个对象的引用。person = ['name', ['saving', 100.0]] # 建立类型hubby = person[:] # 切片拷贝 wifey = list(person) # 列表工厂方法拷贝[id(x) for x in person, hubby, wifey] # 列表解析出内存中id值 >>> hubby[0] = 'joe'>>> wifey[0] = 'jane'>>> hubby, wifey>>> (['joe', ['saving', 100.0]], ['jane', ['saving', 100.0]])>>> hubby[1][1] = 50.00>>> hubby, wifey>>> (['joe', ['saving', 50.0]], ['jane', ['saving', 50.0]])

问题1 :为什么只设置了joe的值,但是jane的值也跟着变化呢?

原因:因为我们只做了一个浅拷贝,对一个对象进行浅拷贝其实是新创建了一个类型跟原对象一样,其内容是原来对象元素的 | 引用 | 直白的说就是,新建了一个对象,但是它的内容 | 引用 | 原来的对象。

因为对象jane的内容引用自joe的内容,所以当joe的内容更改时,jane也随之更改。

序列类型对象的浅拷贝是默认类型拷贝,可以用以下几种方式实施

完全切片操作利用工厂函数,比如list(), dict()等使用copy模块的copy函数

问题2: 为什么对设置wifey名字时,hubby的名字没有改变?

因为在person列表的两个对象中,第一个是字符串,不可变,第二个是可变的列表,当进行浅拷贝时,字符串被显式的拷贝,并新创建一个字符串对象,而列表元素,只是把它的引用复制了一下。

改变前

>>> id(x) for x in hubby>>> [4344118896, 4349387912]>>> [id(x) for x in wifey]>>> [4344118896, 4349387912] # 相同

改变后

>>> id(x) for x in hubby>>> [4350395376, 4349387912]>>> id(x) for x in wifey>>> [4350586624, 4349387912] #列表第1个值的id已经不同,说明是另外创建了对象。

要创建分离的对象,需要使用深拷贝

>>> person = ['name', ['saving', 100.0]] >>> hubby = person>>> import copy>>> wifey = copy.deepcopy(person)>>> [id(x) for x in person, hubby, wifey]>>> [4401609544, 4401609544, 4402474376] #可以看到,wifey的id已经不一样了 >>> hubby[0] = 'joe'>>> wifey[0] = 'jane'>>> hubby,wifey>>> (['joe', ['saving', 100.0]], ['jane', ['saving', 100.0]])>>> hubby[1][1] = 50.00>>> hubby,wifey>>> (['joe', ['saving', 50.0]], ['jane', ['saving', 100.0]]) # 此时,jane的saving不再随着joe改变 #验证一下id看是不是真的改变了 >>> [id(x) for x in hubby]>>> [4402580776, 4401564632]>>> [id(x) for x in wifey]>>> [4401200608, 4401248232]#四个对象都是不一样的了

关于拷贝的警告 1 非容器类型(比如数字,字符串,和其他‘原子’类型的对象没有拷贝一说,浅拷贝是用完全切片来完成的,第二,如果元组变量,只包含原子类型对象,对它的深拷贝将不会进行,如果把person里第二个元素改成(),即使使用深拷贝也只能得到一个浅拷贝


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表