From: SeanMon on 23 Jul 2010 14:30 I was playing around with Python functions returning functions and the scope rules for variables, and encountered this weird behavior that I can't figure out. Why does f1() leave x unbound, but f2() does not? def f1(): x = 0 def g(): x += 1 return x return g1 def f2(): x = [] def g(): x.append(0) return x return g a = f1() b = f2() a() #UnboundLocalError: local variable 'x' referenced before assignment b() #No error,  returned b() #No error, [0, 0] returned From: Benjamin Kaplan on 23 Jul 2010 14:49 On Fri, Jul 23, 2010 at 11:30 AM, SeanMon wrote:> > I was playing around with Python functions returning functions and the > scope rules for variables, and encountered this weird behavior that I > can't figure out. > > Why does f1() leave x unbound, but f2() does not? > > def f1(): >    x = 0 >    def g(): >        x += 1 >        return x >    return g1 > > def f2(): >    x = [] >    def g(): >        x.append(0) >        return x >    return g > > a = f1() > b = f2() > > a() #UnboundLocalError: local variable 'x' referenced before > assignment > b() #No error,  returned > b() #No error, [0, 0] returned > -- It's not closure related at all. Same thing happens at the module level. x = 0 def f1() :    x += 1 #gives UnboundLocalError x = [] def f2() :    x.append(1) #succeeds. The reason for it is that if you have any assignments to the variable in the function, Python creates a new local variable for it. x += 1 is an assignment, not a modification. Python 2.x allows you to assign to the global scope (using the global keyword) but support for assigning to the outer function's scope wasn't added until Python 3 (with the nonlocal keyword) def f1():    x = 0    def g():        nonlocal x        x += 1        return x    return g1 > > http://mail.python.org/mailman/listinfo/python-list From: Dave Angel on 23 Jul 2010 15:51 SeanMon wrote:> I was playing around with Python functions returning functions and the > scope rules for variables, and encountered this weird behavior that I > can't figure out. > > Why does f1() leave x unbound, but f2() does not? > > def f1(): > x = 0 > def g(): > x += 1 > return x > return g1 > > def f2(): > x = [] > def g(): > x.append(0) > return x > return g > > a = f1() > b = f2() > > a() #UnboundLocalError: local variable 'x' referenced before > assignment > b() #No error,  returned > b() #No error, [0, 0] returned > > Your example is more complex than needed. The symptom doesn't need a function closure. >>> def g(): .... x += 1 .... return x ....>>> g() Traceback (most recent call last): File "", line 1, in File "", line 2, in g UnboundLocalError: local variable 'x' referenced before assignment>>> def f(): .... x.append(0) .... return x ....>>> x = [3,5] >>> f() [3, 5, 0]>>> The difference between the functions is that in the first case, x is reassigned; therefore it's a local. But it's not defined before that line, so you get the ref before assign error. In the second case, append() is an in-place operation, and doesn't create a local variable. DaveA From: Terry Reedy on 23 Jul 2010 18:21 On 7/23/2010 2:30 PM, SeanMon wrote:> I was playing around with Python functions returning functions and the > scope rules for variables, and encountered this weird behavior that I > can't figure out. > > Why does f1() leave x unbound, but f2() does not? > > def f1(): > x = 0 > def g(): In 3.x, add nonlocal x> x += 1 > return x > return g1 You meant g def f1(): x = 0 def g(): nonlocal x x += 1 return x return g f=f1() print(f()) print(f()) print(f()) print(f()) 1 2 3 4 -- Terry Jan Reedy