资讯专栏INFORMATION COLUMN

操作之灵魂——拷贝

codercao / 2847人阅读

摘要:原文地址首先需要搞清楚两个概念赋值和引用,对于操作赋值操作程序先新建对象,然后将的值拷贝到中。切片操作属于浅拷贝。

原文地址

首先需要搞清楚两个概念:赋值引用,对于操作 target = source:

赋值操作:程序先新建对象target,然后将source的值拷贝到target中。这里,target和source值相同,但是它们是两个完全不同的对象。

引用操作:程序直接将target指向source,也就是说target和source是同一个对象,target只不过是source的一个别名。

python中没有赋值,只有引用。

>>> source = 12
>>> target = source
>>> target is source
True

如果我们想拷贝一个对象,而不仅仅是创建一个引用,那么该如何操作呢?万能的python提供了两种拷贝机制浅拷贝(shallow copy)、深拷贝(deep copy)供我们选择,浅拷贝和深拷贝的唯一区别在于对嵌套对象的拷贝处理上。

Function Description
copy.copy(x) Return a shallow copy of x.
copy.deepcopy(x) Return a deep copy of x.
exception copy.error Raised for module specific errors.
简单引用:浅拷贝

对于嵌套对象比如说source = [1, 2, [3, 4]],浅拷贝创建新的列表对象target,target中的所有元素均是source中元素的引用,也就是说target中的元素只是source中元素的别名。

切片操作[start:end]属于浅拷贝。

>>> source = [1, 2, [3, 4]]
>>> target = source[:]
>>> source is target
False
>>> for i in range(3):
...     print source[i] is target[i]
...
True
True
True
>>> source[2][2] = "see here"
>>> source, target
([1, 2, [3, "see here"]], [1, 2, [3, "see here"]])


图1. 浅拷贝示意图


递归拷贝:深拷贝

大多时候有浅拷贝就足够了,但是某些情况下深拷贝仍有着举足轻重的作用。

深拷贝,其实就是递归拷贝。也就是说对于嵌套对象比如说source = [1, 2, [3, 4]],深拷贝时创建新的列表对象target,然后递归地将source中的所有对象均拷贝到target中。即如果source中的元素是列表、字典等,那么python将拷贝这些列表、字典中的对象到target中去,就这样迭代下去,直到不存在嵌套结构。

>>> source = [1, 2, [3, 4]]
>>> import copy
>>> target = copy.deepcopy(source)
>>> target is source
False
>>> for i in range(3):
...     print target[i] is source[i]
...
True
True
False
>>> source[2][4] = "see here"
>>> source, target
([1, 2, [3, "see here"]], [1, 2, [3, 4]])


图2. 深拷贝示意图


深拷贝存在两个问题:

对一个递归对象进行深拷贝会导致递归循环。比如values = [values, 2];

由于深拷贝要拷贝所有对象,因此有时候会拷贝多余的内容,比如管理用的数据结构应该在不同拷贝间共享。

不过_deepcopy()_函数提供了两个解决方案避免以上问题:

拷贝过程中维护一个备忘字典"memo",字典中存放已经拷贝过的对象;

允许用户在自定义的类中重写拷贝操作或重写要拷贝的组件。

参考

python的赋值操作
Python Copy Through Assignment?
copy module 学习笔记

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/45282.html

相关文章

  • 前端20个灵魂拷问 彻底搞明白你就是中级前端工程师 【中篇】

    摘要:前端个灵魂拷问,彻底搞明白你就是中级前端工程师上篇感觉大家比较喜欢看这种类型的文章,以后会多一些。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。此规范其实是在推广过程中产生的。 showImg(https://segmentfault.com/img/bVbwAMU?w=700&h=394); 前端20个灵魂拷问,彻底搞明白你就是中级前端工程师...

    MartinDai 评论0 收藏0
  • 前端20个灵魂拷问 彻底搞明白你就是中级前端工程师 【中篇】

    摘要:前端个灵魂拷问,彻底搞明白你就是中级前端工程师上篇感觉大家比较喜欢看这种类型的文章,以后会多一些。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。此规范其实是在推广过程中产生的。 showImg(https://segmentfault.com/img/bVbwAMU?w=700&h=394); 前端20个灵魂拷问,彻底搞明白你就是中级前端工程师...

    coolpail 评论0 收藏0
  • OpenAI 以 10 亿美元出售「灵魂」,网友热评不再「Open」

    摘要:近日,一篇在上成为了网友热议的话题。在这种结构改变几个月后,微软宣布注资亿美元。与微软的合作关系是基于一个重要的前提,即微软有权将的部分技术商业化。网友纷纷称早已应该更名为。 编译 | 禾木木 出品 | AI科技大本营(ID:rgznai100) OpenAI 如何以 10 亿美元的价...

    wenzi 评论0 收藏0
  • 深度剖析js原型及面向对象

    摘要:返回一个对象先说一个最常用的方法构造函数获取所有节点获取节点的长度作用于链式调用测试上面的代码就可以实现的效果因为我没读过源码。 es5版本:(过两天写es6 版本的)由浅入深地讲,先说使用, function person(age, sex) { this.age = age; this.sex = sex; this.clothes ...

    Corwien 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<