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? Is there a penalty for the attrs={} (extra wasted dict creation?)
I’m still too new to python to answer these questions, but I am curious.
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).
——————- 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. Sure, the attrs I force to be there are there, but so is the {'something': 'extra'} that shouldn’t be. This is subtle enough to be good fodder for an obfuscation contest, lookout PERL!
Using
attrs = {}in the function signature will bite you, since it will keep its value on successive calls to the function. The original code is best.eg.
Note how it kept the value assigned the first time, on the second call.