【问题标题】:How do I use [] as a default value for a named function argument in python? [duplicate]如何在 python 中使用 [] 作为命名函数参数的默认值? [复制]
【发布时间】:2012-11-09 03:55:54
【问题描述】:

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

我有这个代码

class Test(object):
  def __init__(self, var1=[]):
    self._var1 = var1

t1 = Test()
t2 = Test()

t1._var1.append([1])

print t2._var1

我得到“[[1]]”作为结果。很明显 t1._var1 和 t2._var1 正在处理同一个列表。如果我把

t3 = Test()
print t3._var1

然后我也得到“[[1]]”。所以 var1=[] 似乎将 var1 永久绑定到 some 列表。我尝试复制列表,

def __init__(self, var1=copy([])):

但得到了相同的结果,因此命名参数的表达式似乎在调用 init 之前被评估,它只是给 var1 一个空列表的副本,然后在实例之间共享。

那么如何使用 [] 作为命名参数的默认值?

【问题讨论】:

  • 它们看起来确实是重复的。抱歉,我在发布之前确实看过,但我没有看到其他问题。话虽如此,其他问题的答案都没有显示如何正确使用可变默认参数。

标签: python constructor named-parameters


【解决方案1】:

如果您希望每个对象都有一个空列表,则不能直接使用[]。我倾向于使用解决方法:

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

如果var1 可以是None,这自然不会起作用,您需要使用不同的对象。

【讨论】:

  • 这是处理可变默认参数的非官方官方推荐模式。 (Example)
  • 这是一个深思熟虑的设计决定吗?理由是什么?为什么不只在调用函数时计算表达式?
  • 这不仅仅是“非正式的官方”,它在常见问题解答中。理由也在那里。详情请见docs.python.org/2/faq/…
  • 如果None是你想要支持的值,你可以创建自己的sentinel值,比如对象实例。例如。 _sentinel = object(); class foo: def __init__(self, foo=_sentinel): if foo is _sentinel: foo = []; ...
  • savagent@ 我写了a general answer to this closed and the related question。特别是:有些copy应该在函数体中创建,而不是在函数头中,以防止其他不必要的副作用。一种好的编程技术是不允许修改使用的实际输入参数,或者只是有意且非常明确地进行。这意味着为最终也可以作为输出的参数指定默认值是令人困惑的。当前的实施不是 IMO 的问题。
猜你喜欢
  • 2012-08-01
  • 1970-01-01
  • 2011-04-03
  • 1970-01-01
  • 2020-09-16
  • 2019-09-11
  • 1970-01-01
  • 2019-04-30
  • 1970-01-01
相关资源
最近更新 更多