python 中的深拷贝和浅拷贝

>>> person = ['name', ['savings', 100.00]]
>>> person
['name', ['savings', 100.0]]
>>> hubby = person[:]
>>> hubby
['name', ['savings', 100.0]]
>>> id(person)
29577736L
>>> id(hubby)
46633160L
>>> wifey = list(person)
>>> wifey
['name', ['savings', 100.0]]
>>> id(wifey)
46606856L
#这是一个亮点的用法,值得记录一下
>>> [id(x) for x in person, hubby, wifey]
[29577736L, 46633160L, 46606856L]






>>> person = ['name', ['savings', 100.00]]
>>> person
['name', ['savings', 100.0]]
>>> hubby = person[:]
>>> hubby
['name', ['savings', 100.0]]
>>> id(person)
29577736L
>>> id(hubby)
46633160L
>>> wifey = list(person)
>>> wifey
['name', ['savings', 100.0]]
>>> id(wifey)
46606856L
>>> [id(x) for x in person, hubby, wifey]
[29577736L, 46633160L, 46606856L]
>>> hubby[0] = 'joe'
>>> hubby
['joe', ['savings', 100.0]]
>>> wifey[0] = 'jane'
>>> wifey
['jane', ['savings', 100.0]]
>>> hubby[1][1] = 50.00
>>> hubby, wifey
(['joe', ['savings', 50.0]], ['jane', ['savings', 50.0]])
原因是我们仅仅做了一个浅拷贝。对一个对象进行浅拷贝其实是新创建了一个类型跟原对象一样,其内容是原来对象元素的引用,换句话说,这个拷贝的对象本身是新的,但是它的内容不是。序列类型对象的浅拷贝是默认类型拷贝,并可以以下几种方式实施:(1)完全切片操作[:],(2)利用工厂函数,比如list(),dict()等,(3)使用copy模块的copy函数。


当妻子的名字被赋值,为什么丈夫的名字没有受到影响?
这是因为在连个列表的两个对象中,第一个对象是不可变的(是个字符串类型),而第二个是可变的(一个列表)。正因为如此,当进行浅拷贝是,字符被显式的拷贝,并新创建了一个字符串对象,而列表元素只是把它的引用复制了一下,并不是它的成员。所以改变名字没有任何问题,但是更改他们银行账号的任何信息都会引发问题。


>>> [id(x) for x in hubby]
[43074984L, 46635592L]
>>> id(hubby)
46633160L
假设我们给这对夫妻创建一个联合账号,上面是一个非常棒的方案,但是,如果需要的是两个分离账户,就需要做些改动了。copy.deepcopy()函数,深度拷贝来重写整个例子。






>>> person = ['name', ['savings', 100.00]]
>>> hubby = person
>>> import copy
>>> wifey = copy.deepcopy(person)
>>> [id(x) for x in person, hubby, wifey]
[46632712L, 46632712L, 46646728L]
>>> hubby[0] = 'joe'
>>> wifey[0] = 'jane'
>>> person, hubby, wifey
(['joe', ['savings', 100.0]], ['joe', ['savings', 100.0]], ['jane', ['savings', 100.0]])
>>> hubby[1][1] = 50.00
>>> person, hubby, wifey
(['joe', ['savings', 50.0]], ['joe', ['savings', 50.0]], ['jane', ['savings', 100.0]])
>>> [id(x) for x in hubby]
[46919472L, 46609416L]
>>> [id(x) for x in wifey]
[43074984L, 46623816L]
关于拷贝操作的警告:
第一,非容器类型(比如数字,字符串和其他“原子”类型的对象,像代码,类型和xtange对象等)没有被拷贝一说,浅拷贝是用完全切片操作来完成的。
第二、如果元组变量只包含原子类型对象,对它的深拷贝将不会进行。如果我们把账户信息改成元组类型,那么即便按我们的要求使用深拷贝操作也只能得到一个浅拷贝:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
浅拷贝深拷贝Python用于复制对象的两种方式。浅拷贝只复制了对象的外层列表,内层列表会跟随原列表进行改变,两者互相影响。而深拷贝则是拷贝了所有的数据,并开辟了一个新的内存地址,原数据和拷贝数据不在同一个地址,两者互不影响。 在Python,赋值语句总是创建对象的引用,而不是复制对象。因此,赋值操作只是拷贝了对象的引用。而拷贝操作是创建了一个新对象,并将原对象的值复制到新对象浅拷贝可以使用多种方法实现,包括使用数据类型本身的构造器、使用copy.copy()函数、使用':'切片操作符以及直接赋值。 深拷贝则可以使用copy模块的deepcopy函数进行实现。 需要注意的是,浅拷贝只拷贝了外层列表,内层列表仍然是引用原对象的子对象。而深拷贝则递归拷贝了所有的子对象,源对象和拷贝对象的子对象也不相同。 总结来说,浅拷贝只拷贝了对象的外层列表,内层列表会跟随原列表进行改变,两者互相影响。而深拷贝则是拷贝了所有的数据,并开辟了一个新的内存地址,原数据和拷贝数据不在同一个地址,两者互不影响。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Python 深拷贝浅拷贝详解](https://blog.csdn.net/qq_40630902/article/details/119278072)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Python浅拷贝深拷贝](https://blog.csdn.net/qq_52703934/article/details/123167223)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值