开发者

Why doesn't a sub-function inherit scope in Python?

开发者 https://www.devze.com 2023-02-28 16:23 出处:网络
I don\'t understand why the following doesn\'t work: def foo( x ): n = 1 summe = 0 def bar(): n -= 1 for i in range(0,10):

I don't understand why the following doesn't work:

def foo( x ):
    n = 1
    summe = 0
    def bar():
        n -= 1
    for i in range(0,10):
        y = x+i+n
        x += i
        summe += y
        print "{0} = {1} + {2} + {3}".format(y,x,i,n)
        bar()
    print "summe =", summe
    return summe

Why is it that bar(开发者_C百科) doesn't inherit the scope of foo()? Is this a C'ism that I need to forget? Is there a way I can make that work?


PEP 3104 provides an explanation and a solution for this problem. The issue is Python treats any assignment to a name as a local variable declaration.

>>> n = 1
>>> def bar():
>>>     n = n + 1
>>> 
>>> bar()
Traceback (most recent call last):
  File "<pyshell#8>", line 1, in <module>
    bar()
  File "<pyshell#7>", line 2, in bar
    n = n + 1
UnboundLocalError: local variable 'n' referenced before assignment

There is a few workarounds for this problem if you use a Python version without the nonlocal keyword. One ugly trick is to wrap your variable in a list:

>>> n=[1]
>>> def bar():
>>>     n[0] = n[0] + 1
>>> 
>>> bar()
>>> n
[2]

Although this trick works, it is usually better to rewrite the code to remove the need for non-local assignments.


I actually found this question while searching for a solution to a slightly different problem. Local variables aren't inherited by sub's inherited but there's nothing stopping you from passing the variable to the inner function and then assigning the results on return.

This is in addition to the nonlocal statement in PEP 3104. It's slightly less ugly and makes memorizing yet another python keyword less crucial.

def foo( x ):
    n = 1
    summe = 0
    def bar(n):
        n -= 1
        return n
    for i in range(0,10):
        n = bar(n)
        y = x+i+n
        x += i
        summe += y
        print "{0} = {1} + {2} + {3}".format(y,x,i,n)
    print "summe =", summe
    return summe
0

精彩评论

暂无评论...
验证码 换一张
取 消