Python:添加到列表中一个对象的dict会更改列表中每个其他对象的所有序列

时间:2016-02-19 18:19:32

标签: python python-3.x

所以Python不是我的强项,而且我遇到了我认为是一个奇怪的问题。我已经将问题缩小到几行代码,简化它以使这个问题变得更容易。我有一个对象列表,这个对象:

class FinalRecord():
     ruid = 0
     drugs = {}

我在shell中创建它们:

finalRecords = []
fr = FinalRecord()
fr.ruid = 7
finalRecords.append(fr)
fr2 = FinalRecord()
fr2.ruid = 10
finalRecords.append(fr2)

一旦我想改变一个物体上的毒品,它就会改变它对另一个物体

finalRecords[0].drugs["Avonex"] = "Found"

我打印出来:

finalRecords[1].drugs

它显示:

{'Avonex':'Found'}

当我期待它实际上是空的时候。我知道我并不完全理解Python如何使用这些对象,任何人都可以帮助我吗?

2 个答案:

答案 0 :(得分:3)

原因是drugs是一个类属性。因此,如果您为一个对象更改它,它实际上会在其他对象中更改。

如果您希望没有此行为,那么您正在寻找实例属性。像__init__这样设置药物:

class FinalRecord():
    def __init__(self):
        self.ruid = 0
        self.drugs = {}

注意使用self,它是对象的引用。

以下是class vs instance attributes

的一些信息

所以,演示了这种行为的完整演示:

>>> class FinalRecord():
...     def __init__(self):
...         self.ruid = 0
...         self.drugs = {}
...
>>> obj1 = FinalRecord()
>>> obj2 = FinalRecord()
>>> obj1.drugs['stuff'] = 2
>>> print(obj1.drugs)
{'stuff': 2}
>>> print(obj2.drugs)
{}

答案 1 :(得分:1)

您将drugs定义为属性,而不是实例属性。因此,您始终在修改同一个对象。您应该在drugs方法中定义__init__。我还建议使用ruid作为参数:

class FinalRecord():
    def __init__(self, ruid):
        self.ruid = ruid
        self.drugs = {}

然后可以将其用作:

fr = FinalRecord(7)
finalRecords.append(fr)
fr2 = FinalRecord(10)
finalRecords.append(fr2)

或更简单:

finalRecords.append(FinalRecord(7))
finalRecords.append(FinalRecord(10))