为什么子函数不在Python中继承范围?

时间:2011-04-24 20:07:04

标签: python scope

我不明白为什么以下不起作用:

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'ism吗?我有办法让这项工作成功吗?

2 个答案:

答案 0 :(得分:15)

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

>>> 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版本,则有一些解决此问题的方法。一个丑陋的技巧是将变量包装在一个列表中:

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

虽然这个技巧有效,但通常最好重写代码以消除对非本地分配的需要。

答案 1 :(得分:1)

我实际上在寻找一个稍微不同的问题的解决方案时发现了这个问题。局部变量不会被子继承继承,但没有什么能阻止你将变量传递给内部函数,然后在返回时分配结果。

这是PEP 3104nonlocal声明的补充。它稍微不那么难看,并且记住另一个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