It is a common mistake in Python to set a mutable object as the default value of an argument in a function. Here's an example taken from this excellent write-up by David Goodger:
>>> def bad_append(new_item, a_list=[]):
a_list.append(new_item)
return a_list
>>> print bad_append('one')
['one']
>>> print bad_append('two')
['one', 'two']
The explanation why this happens is here.
And now for my question: Is there a good use-case for this syntax?
I mean, if everybody who encounters it makes the same mistake, debugs it, understands the issue and from thereon tries to avoid it, what use is there for such syntax?
You can use it to cache values between function calls:
def get_from_cache(name, cache={}):
if name in cache: return cache[name]
cache[name] = result = expensive_calculation()
return result
but usually that sort of thing is done better with a class as you can then have additional attributes to clear the cache etc.
import random
def ten_random_numbers(rng=random):
return [rng.random() for i in xrange(10)]
Uses the random
module, effectively a mutable singleton, as its default random number generator.
Maybe you do not mutate the mutable argument, but do expect a mutable argument:
def foo(x, y, config={}):
my_config = {'debug': True, 'verbose': False}
my_config.update(config)
return bar(x, my_config) + baz(y, my_config)
(Yes, I know you can use config=()
in this particular case, but I find that less clear and less general.)
Canonical answer is this page: http://effbot.org/zone/default-values.htm
It also mentions 3 "good" use cases for mutable default argument:
- binding local variable to current value of outer variable in a callback
- cache/memoization
- local rebinding of global names (for highly optimized code)
EDIT (clarification): The mutable default argument issue is a symptom of a deeper design choice, namely, that default argument values are stored as attributes on the function object. You might ask why this choice was made; as always, such questions are difficult to answer properly. But it certainly has good uses:
Optimising for performance:
def foo(sin=math.sin): ...
Grabbing object values in a closure instead of the variable.
callbacks = []
for i in range(10):
def callback(i=i): ...
callbacks.append(callback)
来源:https://stackoverflow.com/questions/9158294/good-uses-for-mutable-function-argument-default-values