gpt4 book ai didi

python - 这是核心Python编程第二版的错误吗?

转载 作者:行者123 更新时间:2023-12-01 05:33:31 25 4
gpt4 key购买 nike

在一个章节中,作者写了两句自相矛盾的句子。

第一个:

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

我不知道作者为什么要写第二个。我说得对吗?

这是全部 Material :

6.20。 *复制Python对象以及浅拷贝和深拷贝

前面在 3.5 节中,我们描述了对象赋值如何简单地成为对象引用。这意味着当您创建一个对象,然后将该对象分配给另一个变量时,Python 不会复制该对象。相反,它仅复制对该对象的引用。

例如,假设您想为一对年轻夫妇创建一个通用配置文件;称之为人。然后为他们两个复制这个对象。在下面的示例中,我们展示了两种复制对象的方法,一种使用切片,另一种使用工厂函数。为了显示我们有三个不相关的对象,我们使用 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()函数。

您的下一个问题应该是:当妻子的名字被分配时,为什么它没有影响丈夫的名字?他们现在不应该都叫“简”吗?它起作用并且我们没有重复名称的原因是因为每个列表中都有两个对象,第一个是不可变的(字符串),第二个是可变的(列表)。因此,当进行浅拷贝时,会显式复制字符串并创建一个新的(字符串)对象,而列表仅复制其引用,而不复制其成员。因此,更改姓名不是问题,但更改银行信息的任何部分才是问题。在这里,让我们看一下每个列表元素的对象 ID。请注意,银行对象完全相同,并且其中一个对象的更改会影响另一个对象。请注意,在我们更改名称后,新的名称字符串如何替换原始的“名称”字符串:

之前:

>>> [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]

最佳答案

Your next question should be: When the wife's name is assigned, how come it did not affect the husband's name? Shouldn't they both have the name 'jane' now? The reason why it worked and we don't have duplicate names is because of the two objects in each of their lists, the first is immutable (a string) and the second is mutable (a list).

虽然引用的事实是真实的,但这种解释是不正确的。事实上,它之所以有效并且我们没有重复的名称的原因是 wifey[0] = 'jane' 行为 wifey 的元素分配了一个新值>,这是与 hubby 不同的列表。相比之下,hubby[1][1] = 50.0 行没有为 hubby 的元素分配新值。相反,它为 hubby[1] 的元素分配了一个新值,正如前面所讨论的,它与 wifey[1] 是同一对象。

hubby[0]wifey[0] 恰好是不可变值这一事实是正确的,但无关紧要。

您可以按如下方式证明这一点:

person = [[], ['savings', 100.00]]
hubby = list(person)
wifey = list(person)

因此,这两个元素都是可变的,因为它们都是列表。

hubby[0] = [1,2,3]
id(hubby[0])
id(wifey[0])

看哪,现在第一个元素引用了不同的列表!

Because of this, when shallow copies are made, the string is explicitly copied and a new (string) object created while the list only has its reference copied, not its members.

我想不出任何方法可以将其解释为正确。如果您对包含字符串的内容进行浅拷贝,则不会复制该字符串。列表的情况完全相同,如果您对包含列表的内容进行浅拷贝,则不会复制该列表。

如果您复制字符串本身,则实际上不需要复制字符串still(因为它是不可变的)。作为一种优化,您可以再次返回相同的对象,并且对于大多数目的来说,这同样好。事实上,Python 2.7.5 和 Python 3.2.5(这是我在这里安装的)都对 original[:]str(original) 的所有三个进行了优化> 和 copy.copy(original)

如果出于某种晦涩的原因,您实际上想要两个不相同的相等字符串(也许是为了测试 == 的性能或其他东西,我不知道),那么您基本上必须尝试欺骗 Python 运行时:(original + ' ')[0:-1] 或其他。

关于python - 这是核心Python编程第二版的错误吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19630023/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com