讨论copy与deepcopy的区别这个问题要先搞清楚python中的引用、python的内存管理。

python中的一切事物皆为对象,并且规定参数的传递都是对象的引用。可能这样说听起来比较难懂,对比一下PHP中的赋值和引用就有大致的概念了。参考下面一段引用:

1. python不允许程序员选择采用传值还是传引用。Python参数传递采用的肯定是“传对象引用”的方式。实际上,这种方式相当于传值和传引用的一种综合。如果函数收到的是一个可变对象(比如字典或者列表)的引用,就能修改对象的原始值——相当于通过“传引用”来传递对象。如果函数收到的是一个不可变对象(比如数字、字符或者元组)的引用,就不能直接修改原始对象——相当于通过“传值”来传递对象。 
2. 当人们复制列表或字典时,就复制了对象列表的引用同,如果改变引用的值,则修改了原始的参数。 
3. 为了简化内存管理,Python通过引用计数机制实现自动垃圾回收功能,Python中的每个对象都有一个引用计数,用来计数该对象在不同场所分别被引用了多少次。每当引用一次Python对象,相应的引用计数就增1,每当消毁一次Python对象,则相应的引用就减1,只有当引用计数为零时,才真正从内存中删除Python对象。

所谓“传值”也就是赋值的意思了。那么python参数传递有什么特殊呢?看例子:

>>> seq = [1, 2, 3] 
>>> seq_2 = seq 
>>> seq_2.append(4) 
>>> print seq, seq_2 [1, 2, 3, 4] [1, 2, 3, 4] 
>>> seq.append(5) 
>>> print seq, seq_2 [1, 2, 3, 4, 5] [1, 2, 3, 4, 5] 如果按照PHP的语法,seq和seq_2这两个变量对应两个不同的存储地址,自然对应不同的值,是毫无关联的,但是在python中确令我们大跌眼镜。再看下面的例子: >>> a = 1 
>>> b = a 
>>> b = 2 
>>> print a, b 1 2 
>>> c = (1, 2) 
>>> d = c 
>>> d = (1, 2, 3) 
>>> print c, d (1, 2) (1, 2, 3)

显然和上面的例子有冲突吗?看开头引用的话就明白了,当引用的原始对象改变的时候,他俩就没有关系了,也就是说他俩是两个不同对象的引用,对应各自 引用计数加减1;而第一个例子中seq和seq_2都是对原始对象[1, 2, 3]这个lis对象的引用,所以不管append()还是pop()都不会改变原始对象,只是改变了它的元素,这样也就不难理解第二个例子了,因为b = 2就是创建了一个新的 int 对象。

接下来再通过例子看copy与deepcopy的区别:

>>> seq = [1, 2, 3] 
>>> seq_1 = seq 
>>> seq_2 = copy.copy(seq) 
>>> seq_3 = copy.deepcopy(seq) 
>>> seq.append(4) 
>>> print seq, seq_1, seq_2, seq_3 [1, 2, 3, 4] [1, 2, 3, 4] [1, 2, 3] [1, 2, 3] 
>>> seq_2.append(5) 
>>> print seq, seq_1, seq_2, seq_3 [1, 2, 3, 4] [1, 2, 3, 4] [1, 2, 3, 5] [1, 2, 3] 
>>> seq_3.append(6) 
>>> print seq, seq_1, seq_2, seq_3 [1, 2, 3, 4] [1, 2, 3, 4] [1, 2, 3, 5] [1, 2, 3, 6]
这个例子看不出copy之后和之前的联系,也看不出copy与deepcopy的区别。那么再看:
>>> m = [1, ['a'], 2] 
>>> m_1 = m 
>>> m_2 = copy.copy(m) 
>>> m_3 = copy.deepcopy(m) 
>>> m[1].append('b') 
>>> print m, m_1, m_2, m_3 [1, ['a', 'b'], 2] [1, ['a', 'b'], 2] [1, ['a', 'b'], 2] [1, ['a'], 2]
>>> m_2[1].append('c') 
>>> print m, m_1, m_2, m_3 [1, ['a', 'b', 'c'], 2] [1, ['a', 'b', 'c'], 2] [1, ['a', 'b', 'c'], 2][1, ['a'], 2] 
>>> m_3[1].append('d') 
>>> print m, m_1, m_2, m_3 [1, ['a', 'b', 'c'], 2] [1, ['a', 'b', 'c'], 2] [1, ['a', 'b', 'c'], 2][1, ['a', 'd'], 2] 从这就看出来区别了,copy拷贝一个对象,但是对象的属性还是引用原来的,deepcopy拷贝一个对象,把对象里面的属性也做了拷贝,deepcopy之后完全是另一个对象了。再看一个例子: >>> m = [1, [2, 2], [3, 3]] 
>>> n = copy.copy(m) 
>>> n[1].append(2) 
>>> print m, n [1, [2, 2, 2], [3, 3]] [1, [2, 2, 2], [3, 3]] 
>>> n[1] = 0 
>>> print m, n [1, [2, 2, 2], [3, 3]] [1, 0, [3, 3]] 
>>> n[2].append(3) 
>>> print m, n [1, [2, 2, 2], [3, 3, 3]] [1, 0, [3, 3, 3]] 
>>> m[1].pop() 2 
>>> print m, n [1, [2, 2], [3, 3, 3]] [1, 0, [3, 3, 3]] 
>>> m[2].pop() 3 
>>> print m, n [1, [2, 2], [3, 3]] [1, 0, [3, 3]] 最后测试你到底掌握没有: l = [] 
d = {'num': 0, 'sqrt': 0} 
for x in [1, 2, 3]: 
    d['num'] = x 
    d['sqrt'] = x*x 
    l.append(d) 
    print l 由于我主要从事WEB开发,平时主要用framework里面一下package,很少研究python自身的一些东西,不过话说回来,我是用python来工作的,也不是专门研究这门语言的教授之类。时间越久发现python越有趣。 转载请注明出处,未经允许请勿用作商业用途。
本文连接地址:http://luchanghong.com/python/2012/09/21/the-differences-between-copy-and-deepcopy-in-python.html

从python中copy与deepcopy的区别看python引用的更多相关文章

  1. python中copy与deepcopy的区别

    目录 区别 python代码举例 区别 高级语言中变量是对内存及其地址的抽象 copy.copy(object), 拷贝的是内嵌套结构的地址引用,当前到结构发生变化的时候,浅拷贝也相应的改变. cop ...

  2. python中copy()和deepcopy()详解

    **首先直接上结论: —–我们寻常意义的复制就是深复制,即将被复制对象完全再复制一遍作为独立的新个体单独存在.所以改变原有被复制对象不会对已经复制出来的新对象产生影响.—–而浅复制并不会产生一个独立的 ...

  3. python is、==区别;with;gil;python中tuple和list的区别;Python 中的迭代器、生成器、装饰器

    1. is 比较的是两个实例对象是不是完全相同,它们是不是同一个对象,占用的内存地址是否相同 == 比较的是两个对象的内容是否相等 2. with语句时用于对try except finally 的优 ...

  4. copy模块中的copy与deepcopy的区别

    前言 每空闲下来,就觉得以前写的博客很low........也许现在也很low~~~~好吧就当升级版的low吧~~~~ 如果要了解copy与deepcopy的区别,就需要了解Python的存储机制:P ...

  5. Python的copy()与deepcopy()区别

    Python的copy()与deepcopy()分别对应浅拷贝和深拷贝. 它们的理论区别: deepcopy():深复制(也就是寻常意义上的复制),即将被复制对象完全再复制一遍作为独立的新个体单独存在 ...

  6. Python中的is和==的区别,==判断值是否相等,is判断地址是否一致

    Python中的is和==的区别 Python中的对象包含三要素:id.type.value. 其中id用来唯一标示一个对象,type标识对象的类型,value是对象的值. is判断的是a对象是否就是 ...

  7. Python中深拷贝与浅拷贝的区别

    转自:http://blog.csdn.net/u014745194/article/details/70271868 定义: 在Python中对象的赋值其实就是对象的引用.当创建一个对象,把它赋值给 ...

  8. Python中type与Object的区别

    Python中type与Object的区别 在查看了Python的API后,总算明白了.现在总结如下: 先来看object的说明: Python中关于object的说明很少,甚至只有一句话: clas ...

  9. (网页)Angular.js 中 copy 赋值与 = 赋值 区别

    转自st.gg Angular.js 中 copy 赋值与 = 赋值 区别 为什么用 $scope.user = $scope.master; $scope.master 会跟着 $scope.use ...

随机推荐

  1. python中的实例方法、静态方法、类方法、类变量和实例变量

    class MyTest: myname = 'peter' # add a instance attribute    def __init__(self, name):        self.n ...

  2. 算法_队列的Java通用数组实现

    在实现Queue的API的时候,可以使用两个实例变量做索引,一个变量head指向队列的开头,另一个变量tail指向队列的结尾.在删除一个元素的时候,使用head访问,并将head+1,插入一个元素的时 ...

  3. Java 文件IO

    文件IO Java IO    IO流用来处理设备之间的数据传输 Java对数据的操作是通过流的方式 Java用于操作流的对象都在IO包中    按操作数据分为 字节流和字符流        字符流的 ...

  4. POJ 2063 Investment 完全背包

    题目链接:http://poj.org/problem?id=2063 今天果然是卡题的一天.白天被hdu那道01背包的变形卡到现在还没想通就不说了,然后晚上又被这道有个不大也不小的坑的完全背包卡了好 ...

  5. OpenGL中各种坐标系的理解[转]

    OPENGL坐标系可分为:世界坐标系和当前绘图坐标系. 世界坐标系:在OpenGL中,世界坐标系是以屏幕中心为原点(0, 0, 0),且是始终不变的.你面对 屏幕,你的右边是x正轴,上面是y正轴,屏幕 ...

  6. karma+angular

    下面的介绍以karma能正常运行为前提,看karma系列文章:http://www.cnblogs.com/laixiangran/tag/Karma/ 目录结构 步骤 安装 npm install ...

  7. x^y=(x&~y)|(~x&y)证明

    我见过最棒的证明是文氏图:(首先要知道二元布尔代数是集合的特殊情况,所以把X和Y当作两个集合,结论成立,那么在二元布尔代数里面也成立.)左边的圈是X,右边的圈是Y.如果是OR 也就是取或,中间的白色的 ...

  8. SAP MM移动平均价和标准价逻辑

    从收货到领用,S一直都是以标准价格计算,V是实时更新 S 时将差异结转到在产品,产品中,最后结转到生产成本,最终到利润.具有计划性,可以控制考核 V 是实时更新,出现差异直接对应材料中调整.价格可以直 ...

  9. 那些年独自踩过的flascc的坑

    [一个工程中使用多个flascc编译出来的swc] 1.如果是swf工程, 工程中同时使用多个flascc编译出来的swc, 可以顺利通过. 2.如果是swc工程, 工程中同时使用多个flascc编译 ...

  10. computer English

    算法常用术语中英对照Data Structures 基本数据结构Dictionaries 字典PriorityQueues 堆Graph Data Structures 图Set Data Struc ...