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

2024-07-04 05:37:04 发布

您现在位置:Python中文网/ 问答频道 /正文

在一节中,作者写了两句自相矛盾的话。你知道吗

第一个:

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]

Tags: the对象字符串inid列表forstring
1条回答
网友
1楼 · 发布于 2024-07-04 05:37:04

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.

我想不出任何办法来解释这是真的。如果对包含字符串的内容进行浅层复制,则不会复制该字符串。列表的情况也完全相同,如果您对包含列表的内容进行浅表复制,则不会复制该列表。你知道吗

如果您复制了一个字符串本身,那么字符串仍然实际上不需要被复制(因为它是不可变的)。作为一个优化,您可以再次返回相同的对象,对于大多数目的来说,这同样是好的。实际上,Python2.7.5和Python3.2.5(这是我在这里安装的)都对original[:]str(original)copy.copy(original)三者进行了优化。你知道吗

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

相关问题 更多 >

    热门问题