[Python-ideas] Default arguments in Python - the return
George Sakkis
george.sakkis at gmail.com
Sun May 10 22:06:53 CEST 2009
On Sun, May 10, 2009 at 1:00 PM, George Sakkis <george.sakkis at gmail.com> wrote:
> On Sun, May 10, 2009 at 12:10 PM, Arnaud Delobelle
> <arnodel at googlemail.com> wrote:
>
>> 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.
>
> Cute, but that's still a subset of what the dynamic semantics would
> provide; the evaluated thunks would have access to the previously
> defined arguments:
>
> def foo(a, b, d=(a*a+b+b)**0.5, s=1/d):
> return (a,b,d,s)
>
> would be equivalent to
>
> missing = object()
> def foo(a, b, d=missing, s=missing):
> if d is missing:
> d = (a*a+b+b)**0.5
> if s is missing:
> s = 1/d
> return (a,b,d,s)
Just for kicks, here's a decorator that supports dependent dynamically
computed defaults; it uses eval() to create the lambdas on the fly:
@evaldefaults('s','d')
def foo(a, b, d='(a*a+b*b)**0.5', t=0.1, s='(1+t)/(d+t)'):
return (a,b,d,t,s)
print foo(3,4)
#=======
import inspect
import functools
# from http://code.activestate.com/recipes/551779/
from getcallargs import getcallargs
def evaldefaults(*eval_params):
eval_params = frozenset(eval_params)
def decorator(f):
params,_,_,defaults = inspect.getargspec(f)
param2default = dict(zip(params[-len(defaults):], defaults))
if defaults else {}
param2lambda = {}
for p in eval_params:
argsrepr = ','.join(params[:params.index(p)])
param2lambda[p] = eval('lambda %s: %s' % (argsrepr,
param2default[p]),
f.func_globals)
@functools.wraps(f)
def wrapped(*args, **kwargs):
allkwargs,missing = getcallargs(f, *args, **kwargs)
missing_eval_params = eval_params.intersection(missing)
f_locals = {}
for i,param in enumerate(params):
value = allkwargs[param]
if param in missing_eval_params:
allkwargs[param] = value = param2lambda[param](**f_locals)
f_locals[param] = value
return f(**allkwargs)
return wrapped
return decorator
George
More information about the Python-ideas
mailing list