说当你创建一个
对象,然后把它赋给另一个变量的时候,Python 并没有拷贝这个对象,而是拷贝了这个对象的
引用。
比如,假设你想创建一对小夫妻的通用档案,名为person.然后你分别为他俩拷贝一份。
在下面的例子中,我们展示了两种拷贝对象的方式,一种使用了切片操作,另一种用了工厂方
法,为了区分出三个不同的对象,我们使用id()内建函数来显示每个对象的标识符。(我们还
可以用is 操作符来做相同的事情)
>>> person = ['name', ['savings', 100.00]]
>>> hubby = person[:] # slice copy
>>> wifey = list(person) # fac func copy
>>> [id(x) for x in person, hubby, wifey]
[11826320, 12223552, 11850936]
为他们创建了初始有$100 的个人存款帐户。用户名改为定制的名字。但是,当丈夫取走$50
后,他的行为影响到了他妻子的账户,虽然我们进行了分开的拷贝作(当然,前提是我们希望他
们每个人都拥有自己单独的帐号,而不是一个单一的联合帐号。)为什么会这样呢?
>>> hubby[0] = 'joe'
>>> wifey[0] = 'jane'
>>> hubby, wifey
(['joe', ['savings', 100.0]], ['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 函数.
你的下一个问题可能是:当妻子的名字被赋值,为什么丈夫的名字没有受到影响?难道它们
的名字现在不应该都是'jane'了吗?为什么名字没有变成一样的呢?怎么会是这样呢?这是因为
在这两个列表的两个对象中,第一个对象是不可变的(是个字符串类型),而第二个是可变的(一
个列表).正因为如此,当进行浅拷贝时,字符串被显式的拷贝,并新创建了一个字符串对象,而列
表元素只是把它的引用复制了一下,并不是它的成员.所以改变名字没有任何问题,但是更改他
们银行账号的任何信息都会引发问题.现在,让我们分别看一下每个列表的元素的对象ID 值,注
意,银行账号对象是同一个对象,这也是为什么对一个对象进行修改会影响到另一个的原因.注
意在我们改变他们的名字后,新的名字字符串是如何替换原有'名字'字符串的.
BEFORE:
>>> [id(x) for x in hubby]
[9919616, 11826320]
>>> [id(x) for x in wifey]
[9919616, 11826320]
AFTER:
>>> [id(x) for x in hubby]
[12092832, 11826320]
>>> [id(x) for x in wifey]
[12191712, 11826320]
假设我们要给这对夫妻创建一个联合账户,那这是一个非常棒的方案,但是,如果需要的是
两个分离账户,就需要作些改动了.要得到一个完全拷贝或者说深拷贝--创建一个新的容器对象,
包含原有对象元素(引用)全新拷贝的引用--需要copy.deepcopy()函数.我们使用深拷贝来重
写整个例子.
>>> person = ['name', ['savings', 100.00]]
>>> hubby = person
>>> import copy
>>> wifey = copy.deepcopy(person)
>>> [id(x) for x in person, hubby, wifey]
[12242056, 12242056, 12224232]
>>> hubby[0] = 'joe'
>>> wifey[0] = 'jane'
>>> hubby, wifey
(['joe', ['savings', 100.0]], ['jane', ['savings', 100.0]])
>>> hubby[1][1] = 50.00
>>> hubby, wifey
(['joe', ['savings', 50.0]], ['jane', ['savings', 100.0]])
这就是我们想要的方式,作为验证,让我们确认一下所有四个对象都是不同的.
>>> [id(x) for x in hubby]
[12191712, 11826280]
>>> [id(x) for x in wifey]
[12114080, 12224792]
以下有几点关于拷贝操作的警告。第一,非容器类型(比如数字,字符串和其他"原子"类型的
对象,像代码,类型和xrange 对象等)没有被拷贝一说,浅拷贝是用完全切片操作来完成的.第二,
如果元组变量只包含原子类型对象,对它的深拷贝将不会进行.如果我们把账户信息改成元组类
型,那么即便按我们的要求使用深拷贝操作也只能得到一个浅拷贝:
>>> person = ['name', ('savings', 100.00)]
>>> newPerson = copy.deepcopy(person)
>>> [id(x) for x in person, newPerson]
[12225352, 12226112]
>>> [id(x) for x in person]
[9919616, 11800088]
>>> [id(x) for x in newPerson]
[9919616, 11800088]
核心模块: copy
我们刚才描述的浅拷贝和深拷贝操作都可以在copy 模块中找到.其实copy 模块中只有两
个函数可用:copy()进行浅拷贝操作,而deepcopy()进行深拷贝操作.
分享到:
相关推荐
总结来说,理解Python对象的比较、拷贝和参数传递对于编写高效、稳定的代码至关重要。在实际编程中,正确使用这些概念可以帮助避免很多常见的错误和陷阱。在处理复杂数据结构时,尤其需要注意深拷贝和浅拷贝的区别,...
1. copy.copy 浅拷贝 只拷贝父对象,不会拷贝对象的内部的子对象。2. copy.deepcopy 深拷贝 拷贝对象及其子对象一个很好的例子: import copya = [1, 2, 3, 4, [‘a’, ‘b’]] #原始对象b = a #赋值,...
6.20 *拷贝Python对象、浅拷贝和深拷贝 6.21 序列类型小结 6.22 练习 第7章 映像和集合类型 7.1 映射类型:字典 7.2 映射类型操作符 7.3 映射类型的内建函数和工厂函数 7.4 ...
6.20 *拷贝Python对象、浅拷贝和深拷贝 6.21 序列类型小结 6.22 练习 第7章 映像和集合类型 7.1 映射类型:字典 7.1.1 如何创建字典和给字典赋值 7.1.2 如何访问字典中的值 ...
- 在Python中,对象拷贝涉及浅拷贝和深拷贝。浅拷贝只复制对象的引用,而不复制对象本身,而深拷贝会创建对象的一个完全独立的副本。 8. **案例应用**: - 课件中给出了矩形类`Rectangle`的例子,它有两个属性...
6.20 *拷贝python对象、浅拷贝和深拷贝 6.21 序列类型小结 6.22 练习 第7章 映像和集合类型 7.1 映射类型:字典 7.1.1 如何创建字典和给字典赋值 7.1.2 如何访问字典中的值 ...
6.20 *拷贝python对象、浅拷贝和深拷贝 6.21 序列类型小结 6.22 练习 第7章 映像和集合类型 7.1 映射类型:字典 7.1.1 如何创建字典和给字典赋值 7.1.2 如何访问字典中的值 ...
对Python中列表和数组的赋值 中 ,浅拷贝和深拷贝的实例讲解 浅 引⽤: 列表赋值: 1234567>>> a = [1, 2, 3] >>> b = a >>> print b [1, 2, 3] >>> a[0] = 0 >>> print b [0, 2, 3] 解释:[1, 2, 3]被视作⼀个对象...
Python中的对象拷贝分为浅拷贝和深拷贝。浅拷贝只复制对象的引用,而深拷贝会创建新的对象。对于列表和元组,深拷贝可以防止原始对象被意外修改。 6.6 额外讲解 151、for else 方式的循环 `for`循环可以与`else`...
在Python中,浅拷贝(shallow copy)和深拷贝(deep copy)是用于创建对象副本的两种常见方式。它们可以应用于不同类型的对象,如列表、字典、集合等。下面是对浅拷贝和深拷贝的描述: 浅拷贝:浅拷贝是创建一个新...
在Python编程语言中,深拷贝和浅拷贝是两种不同的复制对象的方法,它们涉及到对象内存的管理和数据结构的复制。这两个概念对于理解和处理复杂的对象结构至关重要。 **浅拷贝**: 浅拷贝(Shallow Copy)是创建一个...
需要注意的是,深拷贝虽然可以保证新旧列表完全独立,但如果列表中还包含自定义对象,那么这个对象仍然是浅拷贝。即深拷贝只对标准的可变数据类型如list、dict等进行递归复制。对于包含自定义对象的列表,深拷贝只...
标题中的“Python笔记和快速拷贝”提示我们,这可能是一个关于Python编程语言的学习资料集,其中包含了关于Python基础知识和一种快速数据拷贝方法的教程或笔记。在描述中,内容重复,没有提供额外信息,但我们可以...
Python 拷贝构造函数是面向对象编程中的一个重要概念,特别是在需要复制对象并保持独立性时。在Python中,由于其动态类型系统和垃圾回收机制,对象的复制并不像C++或Java那样需要显式的拷贝构造函数。然而,Python...
Python 112.对象的浅拷贝和深拷贝_内存分析.mp4
在这个主题中,我们将深入探讨四个关键概念:Python的模块化、对象比较与拷贝、函数装饰器以及装饰器传递。 **1. Python模块化** 模块化是Python编程中的一个重要概念,它允许我们将代码组织成小而独立的部分,称为...
Python中的深拷贝和浅拷贝是编程时处理对象复制的关键概念,特别是在处理复杂数据结构时。它们决定了拷贝操作的“深度”,即创建新对象的程度。本文将深入探讨这两种拷贝的区别,以及如何在Python中正确使用它们。 ...
在Python编程语言中,了解对象的赋值、深拷贝和浅拷贝是至关重要的,因为这直接影响到程序中数据的处理和预期行为。以下是对这些概念的详细解释: 1. **Python直接赋值** 当我们将一个对象赋值给另一个变量时,如`...
面向对象编程是Python的核心特性之一,它是一种编程范式,基于“对象”的概念,通过封装、继承和多态等机制来组织代码。在Python中,面向对象编程提供了强大的抽象能力,使得代码更易于理解和维护。 1. **编程思想*...