Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Function closure inconsistency

Reply
Thread Tools

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
 
Reply With Quote
 
 
 
 
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

 
Reply With Quote
 
 
 
 
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

 
Reply With Quote
 
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

 
Reply With Quote
 
 
 
Reply

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 Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
SendInput() inconsistency between 32/64 bit function equivalents =?Utf-8?B?TWFrc2lt?= Windows 64bit 5 02-12-2010 03:55 PM
yield, curry, mix-in, new.function, global, closure, .... what will work? ecir.hana@gmail.com Python 9 04-17-2007 07:33 AM
Strange behavior when printing a returned closure function dartsch@dicad.de Python 2 03-25-2007 11:50 AM
Preserving the argspec of a function after generating a closure Victor Ng Python 1 03-11-2005 08:36 PM
Perl hangs when returning lvalue closure from another lvalue closure Julian Mehnle Perl Misc 0 07-17-2003 03:13 PM



Advertisments