为什么空字典在Python中是一个危险的默认值?

tsc*_*zle 76 python pylint optional-parameters optional-arguments

我把空括号作为Python函数的可选参数的默认值,而pylint(使用Sublime包)告诉我这很危险.有人可以解释为什么会这样吗?而使用None是更好的选择吗?

Bil*_*nch 109

我们来看一个例子:

def f(value, key, hash={}):
    hash[value] = key
    return hash

print f('a', 1)
print f('b', 2)
Run Code Online (Sandbox Code Playgroud)

您可能希望输出的内容:

{'a': 1}
{'b': 2}
Run Code Online (Sandbox Code Playgroud)

但实际输出:

{'a': 1}
{'a': 1, 'b': 2}
Run Code Online (Sandbox Code Playgroud)

  • 我只想说这是一个真正的Python WTF。谁认为这可能是理智的行为? (31认同)
  • 请注意,“hash=dict()”与“hash={}”具有相同的行为。 (12认同)
  • @alper它不是全局变量,您只能在函数范围内访问它,但默认值(如果未提供)将引用您定义为文字的字典。避免这种情况的一种方法是 def func(hash=None): if hash == None: hash = {} ... (6认同)
  • 我有点晚了,但我想对这个例子表示感谢。我在 Python 中没有意识到这一点,所以我想知道为什么空列表/字典被认为是“危险的”。这很有帮助。 (3认同)
  • 谢啦!我没有得到原因:) (2认同)
  • 那么我们如何仍然可以实现与代码匹配的默认值,而不是说“如果h为None:h = {}”,然后继续执行代码? (2认同)

Joh*_*nck 90

只有当你的函数修改参数时才有危险.如果修改默认参数,它将一直持续到下一次调用,因此你的"空"字典将开始包含除第一个之外的调用的值.

是的,None在这种情况下,使用既安全又传统.

  • 这听起来像是 python 中的一个错误,据我所知其他动态编程语言不会有这样的行为 (4认同)
  • 如果函数不修改参数而是泄漏对它的引用(通过返回它、产生它、用它作为参数调用其他函数等等),那么可能会发生相同的问题。我建议*总是*使用“None”,即使该函数是为了避免此类错误而仔细编写的,纯粹是为了对函数进行看似无害的更改不会破坏它。 (3认同)
  • 如果函数没有修改参数,我们是否仍应在最佳实践名称中使用None作为默认值? (2认同)
  • @NightFurry:我犹豫在这里开什么药——“无”通常是最好的选择,但可能不是 100% 的时间。使用你的判断,但如果你不能决定,“无”是一个安全的赌注。 (2认同)
  • 如果其他人偶然发现这个问题,请查看 [this](/sf/answers/3619710601/) 关于函数参数中可选字典的答案。我觉得这是关于如何解决这个问题的更好的讨论。基本上,今天应该类型提示 {key: value} 的可选映射。即`arg:可选[映射[str,str]] =无` (2认同)