On 10 May 2009, at 11:14, Larry Hastings wrote:
George Sakkis wrote:
+0.x for a new keyword that adds dynamic semantics (and removes the need for the sentinel kludge).
We don't need new syntax for it. Here's a proof-of-concept hack that you can do it with a function decorator. import copy
Not that we don't need syntax for default arguments either :) Here is a decorator that does it: def default(**defaults): defaults = defaults.items() def decorator(f): def decorated(*args, **kwargs): for name, val in defaults: kwargs.setdefault(name, val) return f(*args, **kwargs) return decorated return decorator Here it is in action:
z=1 @default(z=z) ... def foo(a, z): ... print a + z ... z=None foo(3) 4
@default(history=[]) ... def bar(x, history): ... history.append(x) ... return list(history) ... map(bar, 'spam') [['s'], ['s', 'p'], ['s', 'p', 'a'], ['s', 'p', 'a', 'm']]
Let's get rid of default arguments altogether, and we will have solved the problem! Furthemore, by removing default arguments from the language, we can let people choose what semantics they want for default arguments. I.e, if they want them to be reevaluated each time, they could write the default decorator as follows (it is exactly the same as the one above except for a pair of parentheses that have been added on one line. def dynamic_default(**defaults): defaults = defaults.items() def decorator(f): def decorated(*args, **kwargs): for name, val in defaults: kwargs.setdefault(name, val()) # ^^ return f(*args, **kwargs) return decorated return decorator Example:
@dynamic_default(l=list) ... def baz(a, l): ... l.append(a) ... return l ... baz(2) [2] baz(3) [3]
;) -- Arnaud