142

In the 2nd case below, Python tries to look for a local variable. When it doesn't find one, why can't it look in the outer scope like it does for the 1st case?

This looks for x in the local scope, then outer scope:

def f1():
    x = 5
    def f2():
         print x

This gives local variable 'x' referenced before assignment error:

def f1():
    x = 5
    def f2():
        x+=1

I am not allowed to modify the signature of function f2() so I can not pass and return values of x. However, I do need a way to modify x. Is there a way to explicitly tell Python to look for a variable name in the outer scope (something similar to the global keyword)?

Python version: 2.7

5
  • 5
    python 3 provides nonlocal for this purpose, but I think it's worth asking why you need to do this. This is a little safer than using global, but still doesn't feel right. Commented Aug 16, 2012 at 12:52
  • 4
    @mgilson there are many good reasons to do this, see e.g. the rationale section in pep-3104. Commented Aug 16, 2012 at 12:58
  • what version of python do you use? Commented Aug 16, 2012 at 13:00
  • @soulcheck I use Python 2.7, edited that in my question. Commented Aug 16, 2012 at 13:02
  • @Dhara sorry, don't know why the comment got posted. It was fairly obvious that you're on 2.7. Commented Aug 16, 2012 at 13:06

2 Answers 2

208

In Python 3.x this is possible:

def f1():
        x = 5
        def f2():
                nonlocal x
                x+=1
        return f2

The problem and a solution to it, for Python 2.x as well, are given in this post. Additionally, please read PEP 3104 for more information on this subject.

Sign up to request clarification or add additional context in comments.

2 Comments

I just looked this up. nonlocal is the statement to use here.
@user1320237 global does not work instead of nonlocal -- that was precisely my question!
84
def f1():
    x = { 'value': 5 }
    def f2():
        x['value'] += 1

Workaround is to use a mutable object and update members of that object. Name binding is tricky in Python, sometimes.

4 Comments

This works, although I ended up using a list with a single element instead of a dictionary. Thanks!
I think it is more correct to use nonlocal or global
Global is not a good idea as it will pollute the global namespace. Nonlocal is a python 3 feature, and this question specified python 2.7.
global doesn't work in py2.7 for question purpose, however x['value'] is harder to write on parent scope than just value, so consider passing value to nested function, and then just returning value from nested scope to parent scope

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.