A gotcha: Python pain point?

Terry Reedy tjreedy at udel.edu
Tue Jun 12 03:53:01 EDT 2007


"Beorn" <bjorns at gmail.com> wrote in message 
news:1181604836.292323.154510 at z28g2000prd.googlegroups.com...
| Consider this example:
|
|  >>> def funcs(x):
|  ...     for i in range(5):
|  ...         def g(): return x + i
|  ...         yield g
|
| I would expect the value of x used in g to be that at the function
| declaration time, as if you've pass g a (x=x) argument,

Since x is constant during the funcs call, does not matter.  Perhaps you 
meant i, which does vary?  If so, put i=i in the header -- or perhaps ii=i 
to give two different names to two things which are made to have the same 
value.

In any case, the simple rule is that default argument expressions in the 
*header* are evaluated at definition time while the *body* (past the doc 
string, if any) is executed after a call.

Some people expect defaults to be executed every call;  others expect part 
of the body to be executed once.  Both get in trouble.  For nested 
functions, outer call time is inner definition time and this can confuses. 
Defining (but delaying the call of) multiple identical inner functions, as 
you do in the first example below, also confuses.

| especially
| after reading this post: http://lua-users.org/wiki/LuaScopingDiscussion

Lua is not Python.

| But:
|
|  >>> [ fun() for fun in list(funcs(1)) ]
|  [5, 5, 5, 5, 5]
|
| Whereas:
|
|  >>> [ fun() for fun in funcs(1) ]
|  [1, 2, 3, 4, 5]

As Calderone explained, the simple rule works as long as one keeps track of 
what is called when.

Terry Jan Reedy






More information about the Python-list mailing list