为什么子函数在 Python 中不继承作用域?



我不明白为什么下面的代码不工作:

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

为什么bar()没有继承foo()的作用域?这是我需要忘记的C主义吗?我有什么办法能做到吗?

PEP 3104对此问题提供了解释和解决方案。问题是Python将对名称的任何赋值视为本地变量声明。

>>> 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

如果您使用的Python版本没有nonlocal关键字,则有一些解决此问题的方法。一个丑陋的技巧是将变量包装在一个列表中:

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

虽然这个技巧是有效的,但通常最好重写代码以消除对非局部赋值的需要。

我实际上是在寻找一个稍微不同的问题的解决方案时发现这个问题的。局部变量不会被子变量继承,但是你可以将变量传递给内部函数,然后在返回时对结果赋值。

这是对PEP 3104中nonlocal语句的补充。它稍微不那么难看,并且使记忆另一个python关键字变得不那么重要。

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

最新更新