Optional parameter object re-used when instantiating multiple objects
Aaron Brady
castironpi at gmail.com
Mon Nov 17 02:42:55 EST 2008
On Nov 17, 12:52 am, Aaron Brady <castiro... at gmail.com> wrote:
> On Nov 16, 8:16 pm, Aaron Brady <castiro... at gmail.com> wrote:
> > On Nov 16, 12:52 am, Steven D'Aprano <st... at REMOVE-THIS-
> > > I've given practical reasons why the
> > > Python choice is better. If you want default argument to be created from
> > > scratch when the function is called, you can get it with little
> > > inconvenience, but the opposite isn't true. It is very difficult to get
> > > static default arguments given a hypothetical Python where default
> > > arguments are created from scratch. There's no simple, easy idiom that
> > > will work. The best I can come up with is a convention:
>
> > 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.
More information about the Python-list
mailing list