A
Aaron Brady
On Nov 16, 12:52 am, Steven D'Aprano <st...@REMOVE-THIS-I'm not so sure.## Default evaluated at definition time. (Current.)# Static arg.
def f( a= [] ):
...# Non-static arg.
def f( a= None ):
if a is None: a= []
Oops. Forgot one, after the subsequent posts.
# Non-static arg.
@nonstatic( a= list )
def f( a ):
...
This can achieve the 'if a is None' effect. 'nonstatic' takes a
callable or a string, '@nonstatic( a= "[]" )'.
I don't see a way to achieve George Sakkis's example:
if y is None: y = x*x
if z is None: z = x+y
Without a change to the language (the other options don't need one).
#emulates 'def foo(x, y=`x*x`, z=`x+y`):'
@nonstatic( y= 'x*x' ) #illegal
@nonstatic( z= 'x+y' ) #illegal
def foo(x, y, z):
return x+y+z
Sorry for the second reply to myself. With a small change, the above
works (excited!), using George Sakkis's 'getcallargs' recipe: 'Recipe
551779: Introspecting call arguments', http://code.activestate.com/recipes/551779/
#emulates 'def foo(x, y=`x*x`, z=`x+y`):'
@nonstatic( y= 'x*x', z= 'x+y', a= '[]' )
def foo(x, y, z, a):
a.append( 0 )
print x, y, z, a
return x+y+z
print foo( 2 )
print foo( 1 )
/Output:
2 4 6 [0]
12
1 1 2 [0]
4
So, + a fraction for adding 'nonstatic' to 'functools', because there
is such high demand for it. We could just say, 'see the "nonstatic"
function!' when newbies ask. + a fraction on string or callable. No
change to language, no new syntax. Note: some concern about the
**kwargs iteration over variables in the same order they appear in the
arguments to the decorator, may be a deal-breaker.
In reply to Steve Holden,
Consider, though, the case were one argument value has to refer to
another. I would say the function body is the proper place to be doing
that computation. You appear to feel the def statement is the
appropriate place. If multiple statements are needed to perform the
argument initialization, how would you then propose the problem should
be solved?
I don't advocate prohibiting initialization of variables in the
function body, just adding this utility decorator. Both places are
appropriate to perform the initialization. I don't imagine the
decorator can cover every use case, just many.
If the **kwargs dictionary can reproduce the order in which the args
appeared, just initialize them in that order. Otherwise, since each
variable can only have one value in **kwargs, loop over the variables,
passing on "NameError: name ... is not defined", until all variables
are defined or no assignments can be made. It requires O( n^2 )
running time only on the first time through, since we can cache the
order that the assignments succeeded in.