在一节中,作者写了两句自相矛盾的话。你知道吗
第一个:
A shallow copy of an object is defined to be a newly created object of the same
type as the original object whose contents are references to the elements in the
original object.
第二条:
when shallow copies are made, the string is explicitly copied and a new (string)
object created
第一句话的意思是字符串对象和列表对象在浅层复制时都是引用(没有显式复制)。你知道吗
第二句意思是字符串对象在浅层复制时被显式复制。你知道吗
我认为第一句话是对的。我认为第二个应该是:
when "wifey[0] = 'jane'" is executed, the string is explicitly copied and a new
(string) object created
我不知道作者为什么要写第二篇。我说得对吗?你知道吗
这是全部材料:
<强>6.20。*复制Python对象以及浅拷贝和深拷贝
在前面的3.5节中,我们描述了对象赋值是如何简单地作为对象引用的。这意味着,当您创建一个对象,然后将该对象赋给另一个变量时,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()函数。你知道吗
你的下一个问题应该是:当妻子的名字被指定时,为什么它不影响丈夫的名字?他们现在不是都应该叫“简”吗?它之所以有效并且我们没有重复的名称,是因为每个列表中有两个对象,第一个是不可变的(字符串),第二个是可变的(列表)。因此,当进行浅层复制时,字符串被显式复制,并创建一个新的(string)对象,而列表只复制其引用,而不复制其成员。因此,更改姓名不是问题,但更改银行信息的任何部分都是问题。这里,让我们看看每个列表元素的对象id。请注意,banking对象是完全相同的,对其中一个对象的更改会影响另一个对象。请注意,在我们更改名称后,新的名称字符串如何替换原始的“name”字符串:
之前:
>>> [id(x) for x in hubby]
[9919616, 11826320]
>>> [id(x) for x in wifey]
[9919616, 11826320]
之后:
>>> [id(x) for x in hubby]
[12092832, 11826320]
>>> [id(x) for x in wifey]
[12191712, 11826320]
这种解释是不正确的,尽管所引用的事实是真实的。事实上,它之所以起作用并且我们没有重复的名称是因为行
wifey[0] = 'jane'
为wifey
的元素分配了一个新的值,这是一个不同于hubby
的列表。相反,行hubby[1][1] = 50.0
没有给元素hubby
赋值。相反,它将一个新值赋给hubby[1]
的元素,如前所述,该元素与wifey[1]
是同一个对象。你知道吗hubby[0]
和wifey[0]
恰好是不可变值这一事实是正确的,但与此无关。你知道吗你可以证明如下:
所以,这两个元素都是可变的,因为它们都是列表。你知道吗
看,现在第一个元素引用不同的列表!你知道吗
我想不出任何办法来解释这是真的。如果对包含字符串的内容进行浅层复制,则不会复制该字符串。列表的情况也完全相同,如果您对包含列表的内容进行浅表复制,则不会复制该列表。你知道吗
如果您复制了一个字符串本身,那么字符串仍然实际上不需要被复制(因为它是不可变的)。作为一个优化,您可以再次返回相同的对象,对于大多数目的来说,这同样是好的。实际上,Python2.7.5和Python3.2.5(这是我在这里安装的)都对
original[:]
、str(original)
和copy.copy(original)
三者进行了优化。你知道吗如果出于某种模糊的原因,您实际上想要两个不相同的相等字符串(可能是为了测试
==
或其他什么的性能,我不知道),那么您基本上必须尝试欺骗Python运行时:(original + ' ')[0:-1]
或其他什么。你知道吗相关问题 更多 >
编程相关推荐