简体   繁体   English

处理 Python 中默认参数的最佳方法?

[英]Best way to deal with default params in Python?

I've got some code (that someone else wrote):我有一些代码(其他人写的):

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

which I think could be re-written as:我认为可以重写为:

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

This would of course fail if someone passed in attrs=None , but is that something to be expected?如果有人通过attrs=None ,这当然会失败,但这是可以预料的吗? Is there a penalty for the attrs={} (extra wasted dict creation?) attrs={}是否有惩罚(额外浪费的字典创建?)

I'm still too new to python to answer these questions, but I am curious.我对 python 还是太陌生,无法回答这些问题,但我很好奇。

When I test this in the interpreter, I get:当我在解释器中对此进行测试时,我得到:

>>> 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'}

How does this ever cause a problem?这怎么会导致问题? Note that I'm ALWAYS adding that dict to the attrs, even if the user specified one (which may actually point to a different problem (I should probably merge the class attribute with an existing one if present).请注意,我总是将该 dict 添加到 attrs,即使用户指定了一个(这实际上可能指向不同的问题(我可能应该将 class 属性与现有的属性合并(如果存在))。

------------------- And to point out the flaw in the above ------------------ ------------------ 并指出上面的缺陷 ------------------

>>> 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'}

Still seems ok, what's the problem?好像还可以,请问有什么问题吗?

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

Ahhh, now I get it, if {'something': 'extra'} is added by some other bit of code, that never gets cleaned up.啊,现在我明白了,如果{'something': 'extra'}被其他一些代码添加,那永远不会被清理。 Sure, the attrs I force to be there are there, but so is the {'something': 'extra'} that shouldn't be.当然,我强迫在那里的 attrs 在那里,但不应该在那里的{'something': 'extra'}也是如此。 This is subtle enough to be good fodder for an obfuscation contest, lookout PERL!这足够微妙,可以作为混淆比赛的好素材,注意 PERL!

Using attrs = {} in the function signature will bite you, since it will keep its value on successive calls to the function.在 function 签名中使用attrs = {}会咬你,因为它会在对 function 的连续调用中保持其值。 The original code is best.最好是原始代码。

eg.例如。

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

Note how it kept the value assigned the first time, on the second call.请注意它如何在第二次调用时保持第一次分配的值。

The problem is the dictionary is created once at function definition, so all calls use the same dictionary.问题是字典在 function 定义处创建一次,因此所有调用都使用相同的字典。 This is usually NOT the intended behavior, hence the tendency for folks to use the =None version.这通常不是预期的行为,因此人们倾向于使用 =None 版本。

Yes.是的。 Default arguments are evaluated at function definition time.默认 arguments 在 function 定义时间进行评估。 If you use a mutable default argument, it will always be the same one.如果您使用可变的默认参数,它将始终是同一个。 So once you modify attrs , it will stay modified.因此,一旦您修改attrs ,它将保持修改状态。

I guess that since your signature specifies attrs={} all users will either provide a dict or won't use this field, making it be {} .我想,由于您的签名指定attrs={}所有用户要么提供一个 dict 要么不使用该字段,使其成为{} Thus, in this case it is almost impossible for someone to pass None - in that case it's their fault.因此,在这种情况下,几乎不可能有人通过None - 在这种情况下,这是他们的错。 However, in this case the dict will be updated across several calls, maybe you don't want this.但是,在这种情况下,dict 将在多个调用中更新,也许你不想要这个。

Always use sensible defaults when using defaults.使用默认值时始终使用合理的默认值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM