1

可能的重复:
Python 中的“Least Astonishment”:可变默认参数

考虑以下 python test.py 模块:

class Container:
    def __init__(self, str_list=[]):
        self.str_list = str_list

    def from_strings(self, st=""):
        self.str_list.append(st)
        return self

o1 = Container().from_strings(st="o1")
o2 = Container().from_strings(st="o2")
o3 = Container().from_strings(st="o3")

def prnt():
    print("o1's list:"+str(o1.str_list))
    print("o2's list:"+str(o2.str_list))
    print("o3's list:"+str(o3.str_list))

if __name__ == '__main__':
    prnt()

为什么输出python test.py

  o1's list:['o1', 'o2', 'o3']
  o2's list:['o1', 'o2', 'o3']
  o3's list:['o1', 'o2', 'o3']

代替:

  o1's list:['o1']
  o2's list:['o2']
  o3's list:['o3']

(似乎我错过了为什么同一模块中不同实例的字段(str_list)可能会混淆。一个指向解释这个概念的python文档的指针将不胜感激)

4

1 回答 1

2

您在构造函数中创建了一个空列表作为默认值:

def __init__(self, str_list=[]):
    self.str_list = str_list

此列表仅创建一次,然后由所有实例共享。如果您想为每个实例创建一个单独的列表,您可以执行以下操作:

def __init__(self, str_list=None):
    self.str_list = [] if str_list is None else str_list

现在每个实例都创建了自己的列表。

编辑:

到底是怎么回事?

您可能使用过默认参数,例如1, 或者'foo'从未遇到过问题。这些是不可操纵的不可变对象。每当你认为你这样做时,你会得到一个新的实例。不可变对象类型的集合包括intstrtuple等。

现在[], a list, 是一个可以操作的可变对象。因此,每当您更改其上的属性时,它都会更改实际对象,并且对它的每次引用都会反映更改。

于 2012-11-18T16:13:54.150 回答