将项目添加到列表的副本意外行为

Posted

技术标签:

【中文标题】将项目添加到列表的副本意外行为【英文标题】:Adding an item to a copy of a list unexpected behavior 【发布时间】:2019-11-06 05:37:41 【问题描述】:

我给你介绍两个functions

class Message:
def __init__(self, text, log):
    self.text = text
    self.log = log

def copy(self):
    return Message(self.text, self.log)

def add(self, more):
    self.text += more
    self.log += more
    return self
msg1 = Message("",[]).add("A")
msg2 = msg1.copy().add("B")
print(msg1.text, msg1.log)
print(msg2.text, msg2.log)

这个prints

A ['A', 'B'] AB ['A', 'B']

这是(对我而言)意想不到的事情发生的地方 -

list_1 = [1]
list_2 = list_1.copy()

list_2 += 'b'
print(list_1)  # prints [1]
print(list_2)  # prints [1,'b']

所以,我似乎无法理解为什么行为与我在两个函数中使用 += 不同。我已经阅读了object.__iadd__ 的文档,但无法真正理解我的问题的解决方案。

【问题讨论】:

【参考方案1】:

在第一种情况下,您将相同的对象 ([]) 传递给 msg1msg2。当您使用msg1 修改该对象时,msg2 也会看到该更改。

如果您想在msg2 中使用不同的对象,您还需要复制log

def copy():
    return Message(self.text, self.log.copy())

这就是你在第二种情况下所做的,这就是它起作用的原因。

【讨论】:

感谢您的回复。 msg1.copy() 不会创建一个全新的列表吗?例如,list[:] 允许我调整我复制的任何内容,只要它是一个简单的列表 msg1.copy()你的代码。不做任何复制。只是任务。如果你想让 python 创建新对象,你必须告诉它这样做。 很抱歉可能会问同样的问题,但我不太明白。这不是我想要任何事情发生,我只是在测试列表的行为。通过使用msg1.copy(),我不会以可能是something = self.log[:] 的方式创建列表吗? 您确实意识到msg.copy()Message 类中定义的方法。仅仅通过调用方法copy() 不会让它复制任何东西。在您的情况下,您定义的 copy() 方法不会进行任何复制。

以上是关于将项目添加到列表的副本意外行为的主要内容,如果未能解决你的问题,请参考以下文章

从目标视图更新 SwiftUI 列表数据会导致意外行为

Power Query:当特定值出现在另一列中时如何将一个添加到列中

添加到自定义 UICollectionViewCell 时出现意外的 CAShapeLayer 行为

双向将字符串的“虚拟”列表绑定到列

如何使用列表推导将元素添加到字典副本?

Vue.js 是不是具有将持久对象的副本添加到重复数组的内置方法