我对局部变量和python (2.7)有一点小问题。
我有一个小代码:
def foo(a):
def bar():
print a
return bar()
>>>foo(5)
5嗯,它是有效的,但是如果想要修改一个,就像这样:
def foo(a):
def bar():
a -= 1
return bar()
>>>foo(5)
UnboundLocalError: local variable 'a' referenced before assignment所以我必须把'a‘改成另一个变量。
但我不明白这种举止。是不是因为当有赋值时,python会在locals()变量中查找,但找不到它?
谢谢。
发布于 2012-03-15 21:46:43
您发现了一些在Python中曾经存在的问题!简而言之,在Python2.x中不能做到这一点(尽管你可以使用simulate),但在3.x中可以使用关键字nonlocal。
请参阅PEP 3104
在2.1版本之前,
对作用域的处理类似于标准C:在一个文件中只有两个作用域级别,全局和局部。在C中,这是函数定义不能嵌套的自然结果。但是在Python中,尽管函数通常是在顶层定义的,但是函数定义可以在任何地方执行。这为Python提供了没有语义的嵌套作用域的语法外观,并产生了一些程序员感到惊讶的不一致--例如,在顶层工作的递归函数在移动到另一个函数内部时将停止工作,因为递归函数本身的名称在其主体范围内将不可见。这违背了一个函数在放置在不同的上下文中时应该保持一致的直觉。下面是一个例子:
def enclosing_function():def factorial(n):如果n< 2: return 1,则返回n* factorial(n - 1) #失败,返回NameError print factorial(5)
通过使绑定在所有封闭作用域中的名称可见,Python 2.1更接近于静态嵌套作用域(参见PEP 227)。这一更改使上面的代码示例按预期工作。但是,由于对名称的任何赋值都隐式地将该名称声明为本地名称,因此不可能在外部范围内重新绑定该名称(除非全局声明强制该名称为全局名称)。因此,下面的代码旨在显示一个可以通过单击按钮来递增和递减的数字,并不像熟悉词法范围的人所期望的那样工作:
def make_scoreboard(frame,score=0):label =标签(Frame) label.pack() for i in -10,-1,1,10:定义增量(step=i):UnboundLocalError =得分+步骤#失败,返回标签‘text’=得分按钮=按钮(frame,text='%+d‘% i,command=increment) button.pack()返回标签
Python语法没有提供一种方法来指示增量中提到的名称分数是指make_scoreboard中绑定的变量分数,而不是增量中的局部变量。Python的用户和开发人员表示有兴趣消除这一限制,以便Python能够完全灵活地使用Algol风格的作用域模型,该模型现在是许多编程语言的标准,包括JavaScript、Perl、Ruby、Scheme、Smalltalk、带有GNU扩展的C和C# 2.0.
发布于 2012-03-15 21:45:14
Constantinius给出的理由是正确的。处理它的另一种方法(不使用全局变量)是
def foo(a):
def bar(a):
a -= 1
return a
return bar(a)
>>> print foo(5)
4https://stackoverflow.com/questions/9720626
复制相似问题