Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Python (http://www.velocityreviews.com/forums/f43-python.html)
-   -   Function closure inconsistency (http://www.velocityreviews.com/forums/t729062-function-closure-inconsistency.html)

SeanMon 07-23-2010 06:30 PM

Function closure inconsistency
 
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 07-23-2010 06:49 PM

Re: Function closure inconsistency
 
On Fri, Jul 23, 2010 at 11:30 AM, SeanMon <smono927@gmail.com> 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 07-23-2010 07:51 PM

Re: Function closure inconsistency
 
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 07-23-2010 10:21 PM

Re: Function closure inconsistency
 
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



All times are GMT. The time now is 03:56 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.