为什么这个对非局部作用域的变量引用不能解析?

2024-09-27 00:18:53 发布

您现在位置:Python中文网/ 问答频道 /正文

下面是一个为正整数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。。。在

spyder's outcome

但是在pythontutor.com网站,上面写着NameError: name 'testerNum' is not definedlink)。在

pythontutor's outcome

在Spyder中,我认为global testerNum是个问题,因为{}不在全局范围内。它在函数gcdFinder的范围内。这个描述正确吗?如果是这样,斯派德是如何给出答案的?

Q2:在pythontor中,说出最后一个屏幕截图,如何解决pythontutor中的名称错误问题?在

Q3:为什么Spyder和Pythontor的结果存在差异,哪个是正确的?

Q4:不使用global方法更好吗?在

更新:Spyder问题是由于上次运行时存储的值造成的,因此它已经被定义为9。这使得global testerNum起作用。我已经删除了第一季度和第三季度。在


Tags: and答案returnifdef数字globaltester
3条回答

问题:

当试图解析变量引用时,Python首先检查本地范围,然后检查任何封闭函数的本地范围。例如,此代码:

def foo():
    x=23
    def bar():
        return x +1
    return bar

print(foo()())

将运行并打印出24,因为当xbar内被引用时,由于本地作用域中没有x,它在封闭函数(foo)的作用域中找到它。但是,一旦您试图赋值给一个变量,Python就假定它是在本地范围内定义的。所以这个:

^{pr2}$

将抛出一个UnboundLocalError,因为我试图分配给x,这意味着它将在本地作用域中查找,但我试图分配给它的值是基于封闭作用域中的x。由于赋值将x的搜索限制在本地范围内,因此找不到它,我得到了错误。在

因此,您的错误出现是因为else子句中的testerNum -= 1行,它将搜索testerNum限制在它不存在的本地范围内。在

修复:

global声明不正确,因为正如您所指出的,testerNum没有在全局范围内定义。我不熟悉Spyder,也不知道它为什么在那里工作,但它似乎在全局范围内有一个testerNum变量。在

如果您使用Python3,那么可以通过将global testerNum行改为nonlocal testerNum来解决这个问题,这只是告诉Python,尽管被分配了,testerNum并没有在本地范围内定义,而是继续向外搜索。在

def foo():
    x=23
    def bar():
        nonlocal x
        x = x + 1
        return x
    return bar

>>> print(foo()())
24

Python2或3中的另一个方法是传递testerNum,正如Brambor在他们的答案中所描述的那样。在

为了只回答问题4,是的,最好不要使用globalglobal通常会突出糟糕的代码设计。在

这会带来很多麻烦;我强烈建议您查找计算GCD的标准方法,并实现Euclid算法。作为练习留给学生的编码细节。在

对第2季度和第4季度的回答。在

正如我在评论中所写的,您可以将testerNum解析为参数。在

然后您的代码将如下所示:

def gcdFinder(a, b):

    testerNum = a   

    def tester(a, b, testerNum):
        if b % testerNum == 0 and a % testerNum == 0:
            return testerNum
        else:
            testerNum -= 1
            return tester(a, b, testerNum)  # you have to return this in order for the code to work

    return tester(a, b, testerNum)

print(gcdFinder(9, 15))

编辑:(见coment)

相关问题 更多 >

    热门问题