这里有一个例子可以找到正整数a
和b
以及a <= b
的最大公约数。我从较小的a
开始,一个接一个地减,检查它是否是两个数字的除数。
def gcdFinder(a, b):
testerNum = a
def tester(a, b):
if b % testerNum == 0 and a % testerNum == 0:
return testerNum
else:
testerNum -= 1
tester(a, b)
return tester(a, b)
print(gcdFinder(9, 15))
然后,我收到错误信息,
UnboundLocalError: local variable 'testerNum' referenced before assignment
。使用
global testerNum
后,在Spyder控制台中成功地显示了答案3
。。。但在pythontutor.com上,它说的是
NameError: name 'testerNum' is not defined
(link)。问题1:在Spyder中,我认为
global testerNum
是一个问题,因为testerNum = a
不在全局范围内。它在功能范围内。这个描述正确吗?如果是的话,斯皮德是如何给出答案的?问2:在pythontutor中,说最后一张截图,如何解决pythontutor中的NameError问题?
问题3:为什么Spyder和Pythonutor的结果不同,哪一个是正确的?
问题4:最好不要使用
gcdFinder
方法吗?--
更新:Spyder问题是由于上次运行中存储的值造成的,因此已将其定义为
global
。这使得9
工作。我已经删除了第一季度和第三季度。 最佳答案
问题是:
当试图解析变量引用时,Python首先检查所有封闭函数的本地作用域,然后检查其本地作用域。例如,此代码:
def foo():
x=23
def bar():
return x +1
return bar
print(foo()())
将运行并打印出
24
,因为当x
在bar
内被引用时,由于本地作用域中没有x
,它会在封闭函数的作用域中找到它(foo
)。但是,只要您尝试分配给变量,Python就假定它是在本地作用域中定义的。所以这个:def foo():
x=23
def bar():
x = x + 1
return x
return bar
print(foo()())
将抛出一个
UnboundLocalError
,因为我正试图分配给x
,这意味着它将在本地作用域中查找,但我正试图分配给它的值是基于封闭作用域中的x
。由于赋值将对x
的搜索限制在本地范围内,因此找不到它,我得到错误信息。所以你的错误出现了,因为在你的其他子句中有一个cc行,它将搜索的限制限制在它不存在的本地范围内。
修正:
testerNum -= 1
声明不正确,因为正如您所指出的,testerNum
没有在全局范围内定义。我不熟悉Spyder,也不知道它为什么在那里工作,但似乎它的全局范围内有一个global
变量。如果您正在使用Python3,那么可以通过将
testerNum
行更改为testerNum
来解决这个问题,这只会告诉Python,尽管被分配给了,testerNum并没有在本地范围内定义,而是继续向外搜索。def foo():
x=23
def bar():
nonlocal x
x = x + 1
return x
return bar
>>> print(foo()())
24
在Python 2或Python 3中可以使用的另一个选项是传递Brambor在其答案中概述的
global testerNum
。