Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to deal with default params in Python?

Tags:

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? 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!

like image 284
boatcoder Avatar asked Aug 10 '11 20:08

boatcoder


People also ask

How do you set a default value for a parameter in Python?

The default value is assigned by using the assignment(=) operator of the form keywordname=value.

Does Python allow default values for parameters?

Function arguments can have default values in Python. We can provide a default value to an argument by using the assignment operator (=). Here is an example.

Where should the default value of parameter is specified?

Default parameter values must appear on the declaration, since that is the only thing that the caller sees.

Why is it convenient to define functions with default arguments?

Assigning a default value to a keyword argument is very common when defining a Python function. Because it can avoid potential bugs, this practice is strongly recommended if we cannot make sure whether the keyword argument will always receive a value or not.


1 Answers

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.

>>> 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.

like image 123
Gerrat Avatar answered Oct 04 '22 07:10

Gerrat