views:

52

answers:

3

I'm trying to implement a closure in Python 2.6 and I need to access a nonlocal variable but it seems like this keyword is not available in python 2.x. How should one access nonlocal variables in closures in these versions of python?

A: 

you can pass on the value, if you don't intend to modify it.

if you want to use nonlocal x, use:

def inner(a, b, .., x=x):
    # ...
mykhal
You won't be changing the value of x in the outer scope. When you use nonlocal in python 3 you can change the value of x. Read the final example in this section of the faq: http://docs.python.org/py3k/faq/programming.html?why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value#why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value
PreludeAndFugue
@PreludeAndFugue you're right. my "fake" solution only provides read-only access of the non-local variable. however, it might be sufficient fo some uses. *edited the answer*
mykhal
+2  A: 

Python can read nonlocal variables in 2.x, just not change them. This is annoying, but you can work around it. Just declare a dictionary, and store your variables as elements therein.

To use the example from Wikipedia:

def outer():
    d = {'y' : 0}
    def inner():
        d['y'] += 1
        return d['y']
    return inner

f = outer()
print(f(), f(), f()) #prints 1 2 3
Chris B.
A: 

I think the key here is what you mean by "access". There should be no issue with reading a variable outside of the closure scope, e.g.,

x = 3
def outer():
    def inner():
        print x
    inner()
outer()

should work as expected (printing 3). However, overriding the value of x does not work, e.g.,

x = 3
def outer():
    def inner():
        x = 5
    inner()
outer()
print x

will still print 3. From my understanding of PEP-3104 this is what the nonlocal keyword is meant to cover. As mentioned in the PEP, you can use a class to accomplish the same thing (kind of messy):

class Namespace(object): pass
ns = Namespace()
ns.x = 3
def outer():
    def inner():
        ns.x = 5
    inner()
outer()
print ns.x
ig0774