为什么这段代码生成三个数组值而不是一个? python 3.x

时间:2016-04-14 23:31:44

标签: python python-3.x

我有一个名为general的类,其数组为msgs[]作为属性。还有一个名为msg的属性,它是一个字符串。我实例化了三个类gen0, gen1, gen2并将每个对象存储在一个名为arr (arr = [gen0, gen1, gen2])的数组中。

我在类general上定义了一个名为snd(self, id, somemsg)的方法,给定了id(指向数组id中索引arr处的对象),将字符串somemsg附加到数组msgs[]。 例如,gen0.snd(1,"hello")将执行gen1.msgs.append("hello")

def snd(self, dst, msg):
    listGens[dst].msgs.append(msg)

我定义了以下函数,其中general是上面定义的类的实例化。

def playGeneral(general):
    for val in listGens:
        if(val.id is general.id):
            general.snd(general.id, " ")
            continue
        general.snd(val.id, general.oc)

调用playGeneral(gen0)时,somemsg变量已设置为genX.msg = "A",即gen0.msg,恰好是“A”;这样做,我们得到

playGeneral(listGens[0])
    for val in listGens:
    print(val.msgs)

[' ', 'A', 'A']
[' ', 'A', 'A']
[' ', 'A', 'A']

我无法理解为什么会这样。它应该是屈服的

[' ']
['A']
['A']

1 个答案:

答案 0 :(得分:2)

心理调试:您的general类定义如下:

class general:
    msgs = []

或:

class general:
    def __init__(self, msgs=[]):
        self.msgs = msgs

前者使msgs成为类属性,而不是实例属性,因此它在类及其所有实例之间共享,而后者与所有使用默认值的实例共享一个list msgs。两者的解决方案是相同的:为每个使用唯一的list

class general:
    def __init__(self, msgs=()):
        self.msgs = list(msgs)  # Explicitly convert and shallow copy as list

第三种可能性是你做了一些愚蠢的事情,如msgs = []gen0 = general(msgs)gen1 = general(msgs)等,或gen0 = gen1 = gen2 = general([]),或listgens = [general()] * 3等,所有这些归结为同样的问题:你多次存储对同一数据的单个引用,你需要有不同的值。