Velocity Reviews > Function closure inconsistency

# Function closure inconsistency

SeanMon
Guest
Posts: n/a

 07-23-2010
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, [0] returned
b() #No error, [0, 0] returned

Benjamin Kaplan
Guest
Posts: n/a

 07-23-2010
On Fri, Jul 23, 2010 at 11:30 AM, SeanMon <(E-Mail Removed)> 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, [0] 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

Dave Angel
Guest
Posts: n/a

 07-23-2010
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, [0] 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 "<stdin>", line 1, in <module>
File "<stdin>", 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

Terry Reedy
Guest
Posts: n/a

 07-23-2010
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

 Thread Tools

 Posting Rules You may not post new threads You may not post replies You may not post attachments You may not edit your posts BB code is On Smilies are On [IMG] code is On HTML code is OffTrackbacks are On Pingbacks are On Refbacks are Off Forum Rules

 Similar Threads Thread Thread Starter Forum Replies Last Post =?Utf-8?B?TWFrc2lt?= Windows 64bit 5 02-12-2010 03:55 PM ecir.hana@gmail.com Python 9 04-17-2007 07:33 AM dartsch@dicad.de Python 2 03-25-2007 11:50 AM Victor Ng Python 1 03-11-2005 08:36 PM Julian Mehnle Perl Misc 0 07-17-2003 03:13 PM

Advertisments