Python - 使用带有空列表默认​​值的命名构造函数参数时的意外行为

时间:2011-07-26 11:33:13

标签: python

  

可能重复:
  “Least Astonishment” in Python: The Mutable Default Argument

我显然在这里遗漏了一些内容:任何人都可以解释为什么t1“神秘地”获得self.thelist t2的价值?我做错了什么?

>>> class ThingyWithAList(object):
...     def __init__(self, alist=[]):
...         super(ThingyWithAList, self).__init__()
...         self.thelist = alist
... 
>>> t1 = ThingyWithAList()
>>> t1.thelist.append('foo')
>>> t1.thelist.append('bar')
>>> print t1, t1.thelist
<__main__.ThingyWithAList object at 0x1004a8350> ['foo', 'bar']
>>> 
>>> t2 = ThingyWithAList()
>>> print t2, t2.thelist
<__main__.ThingyWithAList object at 0x1004a8210> ['foo', 'bar']

3 个答案:

答案 0 :(得分:3)

因为默认参数'alist = []',所以在读取模块时只创建一个列表。这个单一列表成为__init__“的默认参数,并由所有Thingys共享。

尝试使用None作为虚拟符号,意味着“在此处创建一个新的空列表”。 E.g。

def __init__(self, alist=None):
     super(ThingyWithAList, self).__init__()
     self.thelist = [] if alist is None else alist

答案 1 :(得分:2)

如果我做对了,构造函数中用[]创建的对象引用保持不变。试试这个:

>>> class ThingyWithAList(object):
...     def __init__(self, alist=None):
...         super(ThingyWithAList, self).__init__()
...         self.thelist = alist or []
... 
>>> t1 = ThingyWithAList()
>>> t1.thelist.append('foo')
>>> t1.thelist.append('bar')
>>> print t1, t1.thelist
<__main__.ThingyWithAList object at 0xb75099ac> ['foo', 'bar']
>>> 
>>> t2 = ThingyWithAList()
>>> print t2, t2.thelist
<__main__.ThingyWithAList object at 0xb7509a6c> []

答案 2 :(得分:2)

“特殊情况不够特别”,因此有条不紊地检查“无”会以错误的方式揉搓我。如果.thelist确实是一个列表很重要,那么该类也应该强制执行它。

def __init__(self, alist=()):
    super(ThingyWithAList, self).__init__()
    self.thelist = list(alist)

请注意,现在没有修改默认arg的危险,因为元组是不可变的。