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