On Mon, Nov 30, 2009 at 11:24 AM, spir <denis.s...@free.fr> wrote: > Hello, > > Below startup definitions: > > x = 1 > > def f(): > n = 1 > def g0(a): > print (x + n + a) > return g0 > > > I'm surprised the snippet below works as expected (py 2.6) without any trick: > > g = f() > g(1) # --> 3 > > This means a (real) closure is built for g0, or what? > Thought I would need instead to use the old trick of pseudo > default-parameters: > > def f(): > n = 1 > def g0(a, n=n, x=x): > print (x + n + a) > return g0 > > to let the inner func g0 "remember" outer values. Why is this idiom used, > then? Has something changed, or do I miss a relevant point?
A real closure is indeed created, but you are missing something. Consider this python session: >>> x = 0 >>> def f(): x = x + 1 >>> f() Traceback (most recent call last): File "<pyshell#27>", line 1, in <module> f() File "<pyshell#26>", line 2, in f x = x + 1 UnboundLocalError: local variable 'x' referenced before assignment The python docs offers some insight: The execution of a function introduces a new symbol table used for the local variables of the function. More precisely, all variable assignments in a function store the value in the local symbol table; whereas variable references first look in the local symbol table, then in the local symbol tables of enclosing functions, then in the global symbol table, and finally in the table of built-in names. Thus, global variables cannot be directly assigned a value within a function (unless named in a global statement), although they may be referenced. ( from http://docs.python.org/tutorial/controlflow.html#defining-functions ) In short, the problem is that writing "x =" will create a new (unbound) local name for x, hiding the global one. The following reference to x will find the local unbound variable and start complaining. If you wanted to create a local variable, your idiom is the fix you want. If you want to modify the global one, use the 'global x' statement to tell the interpreter that explicitly. > The bit below also works: > > x = 2 > ... > g(1) # --> 4 > > which seems to indicate python really embeds "symbolic references" (*) to > outer *variables*, when creating a closure for g0. Not "pointer references" > (**), otherwise the replacement of x would not be seen by the closure --like > in the case of default-parameter. > Actually, I find this _Bad_. Obviously, the func's behaviour and result > depend on arbitrary external values (referentially opaque). What do you think? I don't quite understand the point you're trying to make. The code you're showing above seems like what is 'proper' behaviour to me. Can you show an example demonstrating why it is bad? Hugo _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor