在Python中处理默认参数的最佳方法是什么?

时间:2011-08-10 20:33:20

标签: python

我有一些代码(其他人写的):

def render(self, name, value, attrs=None):
    if not attrs:
        attrs = {}
    attrs.update({'class': 'ui-autocomplete-input'})

我认为可以重写为:

def render(self, name, value, attrs={}):
    attrs.update({'class': 'ui-autocomplete-input'})

如果有人传入attrs=None,这当然会失败,但这是否有所期待? attrs={}是否会受到惩罚(额外浪费的dict创作?)

我仍然不熟悉python来回答这些问题,但我很好奇。

当我在口译员中测试时,我得到:

>>> def x(attrs={}):
...   attrs.update({'a': 'b'})
...   print attrs
... 
>>> x({'b': 'c'})
{'a': 'b', 'b': 'c'}
>>> x({'d': 'e'})
{'a': 'b', 'd': 'e'}
>>> x()
{'a': 'b'}

这是如何导致问题的?请注意,我总是将该dict添加到attrs,即使用户指定了一个(实际上可能指向一个不同的问题(我应该将class属性与现有的属性合并,如果存在)。

-------------------并指出上述缺陷------------------ < / p>

>>> def yikes(attrs):
...   attrs.update({'something': 'extra'})
...   print attrs
>>> def x(attrs={}):
...   print "Before:", attrs
...   attrs.update({'a': 'b'})
...   print "After:", attrs
...   yikes(attrs)

>>> x({"b": "c"})
Before: {'b': 'c'}
After: {'a': 'b', 'b': 'c'}
{'a': 'b', 'b': 'c', 'something': 'extra'}
>>> x()
Before: {}
After: {'a': 'b'}
{'a': 'b', 'something': 'extra'}

似乎还不错,问题是什么?

>>> x()
Before: {'a': 'b', 'something': 'extra'}
After: {'a': 'b', 'something': 'extra'}
{'a': 'b', 'something': 'extra'}

啊,现在我知道,如果{'something': 'extra'}被其他一些代码添加,那么永远不会被清除。当然,我强迫那里的人都在那里,但{'something': 'extra'}也不应该。这是一个微妙的足以成为混淆比赛的好饲料,了解PERL!

4 个答案:

答案 0 :(得分:13)

在函数签名中使用attrs = {}会让你感到困惑,因为它会在对函数的连续调用中保持其值。原始代码是最好的。

例如

>>> def a(attrs= {}):
...   print attrs
...   attrs.update({1:1})
...
>>> a()
{}
>>> a()
{1: 1}

请注意第二次调用时它是如何保留第一次分配的值。

答案 1 :(得分:2)

我想,由于您的签名指定attrs={},所有用户都会提供字典或不会使用此字段,使其成为{}。因此,在这种情况下,某人几乎不可能通过None - 在这种情况下,这是他们的错。但是,在这种情况下,dict将在多个调用中更新,也许您不希望这样。

使用默认值时始终使用合理的默认值。

答案 2 :(得分:2)

问题是字典是在函数定义时创建的,因此所有调用都使用相同的字典。这通常不是预期的行为,因此人们倾向于使用= None版本。

答案 3 :(得分:2)

是。在函数定义时计算默认参数。如果使用可变的默认参数,它将始终是相同的。因此,一旦修改attrs,它就会保持修改。