这里有一个例子可以找到正整数ab以及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。。。
python - 为什么这个对非本地作用域的变量引用无法解析?-LMLPHP
但在pythontutor.com上,它说的是NameError: name 'testerNum' is not definedlink)。
python - 为什么这个对非本地作用域的变量引用无法解析?-LMLPHP
问题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,因为当xbar内被引用时,由于本地作用域中没有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

09-25 18:59