问题
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?
回答1:
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.
回答2:
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.)
回答3:
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.
回答4:
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)
回答5:
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