Python3方法由于UnboundLocalError而不可调用



考虑以下代码:

def main():
print('Calling methodA()')
methodA()
print('Calling methodB(True)')
methodB(True)
print('Calling methodB(False)')
try:
methodB(False)
except UnboundLocalError as error:
print(f'--> "UnboundLocalError" raised: {error}')

def methodA():
print('Running methodA()')
print('"method_original" in globals(): ' + str('method_original' in globals()))
method_original()
def methodB(patch_function):
print(f'Running methodB({patch_function})')
print('"method_original" in globals(): ' + str('method_original' in globals()))
if patch_function:
method_original=method_patched
method_original()
def method_original():
print('Running method_original()')
def method_patched():
print('Running method_patched()')

if __name__ == '__main__':
main()

输出如下:

Calling methodA()
Running methodA()
"method_original" in globals(): True
Running method_original()
Calling methodB(True)
Running methodB(True)
"method_original" in globals(): True
Running method_patched()
Calling methodA(False)
Running methodB(False)
"method_original" in globals(): True
--> "UnboundLocalError" raised: local variable 'method_original' referenced before assignment

这没有意义,因为"method_original"在globals()中。这个错误可以简单地在methodB()的开头添加global method_original来修复,但是在某些情况下,我们有很多函数,把它们都放在每个方法的开头可能是一件很痛苦的事情。

有什么规则可以避免这种行为吗?

//BR !

让我用一个更简单的例子来解释:

def fn(a):
if a % 2 == 0:
x = a
return x
print(fn(10))  # Fine
print(fn(9))   # UnboundLocalError: local variable 'x' referenced before assignment

在编译时,当解释器到达函数时,它看到有对x的赋值,因此将x标记为&;local&;;变量。然后在"运行时间"中解释器试图只在本地命名空间中找到它!另一方面,只有当a是偶数时才定义x

如果它出现在全局命名空间中并不重要,现在我想在我的示例中添加一个名为x的全局变量:

def fn(a):
if a % 2 == 0:
x = a
return x
x = 50

print(fn(10))  # Fine
print(fn(9))   # UnboundLocalError: local variable 'x' referenced before assignment

并没有什么改变。解释器仍然试图在中找到x本地命名空间中的函数。

同样的事情发生在你的例子中。

显示哪些变量是"local"

def fn(a):
if a % 2 == 0:
x = a
return x
print(fn.__code__.co_varnames)

co_varnames是包含局部变量名的元组(从参数名开始)


解决方案:

要么使用global(我看到你不喜欢),或者不要在函数内进行赋值,例如将methodB更改为:

def methodB(patch_function):
print(f'Running methodB({patch_function})')
print('"method_original" in globals(): ' + str('method_original' in globals()))
if patch_function:
method_patched()
else:
method_original()

相关内容

  • 没有找到相关文章

最新更新