python 3 中的嵌套函数内部变量如何工作?
how local variables work inside nest function in python 3?
我有代码:
def main(m):
res = m
def help(a, b):
print(res)
#res = min(res, a*b)
help(3,2)
return res
main(3)
代码有效。不过
def main(m):
res = m
def help(a, b):
print(res)
res = min(res, a*b)
help(3,2)
return res
main(3)
提高UnboundLocalError: local variable 'res' referenced before assignment
def main(m):
global res
res = m
def help(a, b):
print(res)
res = min(res, a*b)
help(3,2)
return res
main(3)
好像我加了global res
也没变。这里发生了什么?如何在函数 help
?
中更新 res
问题是您在 help()
函数中引入了一个新的、未初始化的局部变量,然后试图将其传递给 min(res, a*b)
函数。
您可以 return min(res, a*b)
并将其分配给 help()
函数之外的 res
,而不是尝试处理范围问题:
def main(m):
res = m
def help(a, b):
# print(res)
return min(res, a*b)
res = help(3,2)
return res
你需要告诉内部函数 res
变量是非本地的,像这样:
def main(m):
res = m
def help(a, b):
nonlocal res
print(res)
res = min(res, a*b)
help(3,2)
return res
main(3)
您可以在函数中读取非局部作用域变量而不会出现问题,但如果您尝试写入变量,则 python 假定您要创建一个新的局部作用域变量。该局部变量隐藏并阻止访问可能存在于更高范围的命名空间中的任何类似命名的变量,例如外部函数或全局变量。要通知它您不想创建局部变量并想访问外部范围变量,您需要使用 nonlocal
关键字,如上例所示。
使用 global res
无法修复它,因为全局变量位于命名空间层次结构的顶层,而您尝试访问的 res
变量不是。您要访问的 res
位于全局范围和本地范围之间。这就是为什么您需要使用 nonlocal
而不是 global
。如果 res
处于 top/external 级别,那么 global
就是解决方案。
这里的相关代码是
res = m
def help(a, b):
print(res)
res = min(res, a*b) # may or may not be commented out
这不是你想的那样。
让我们逐行分析一下:
res = m
:这定义了变量 res
,值为 m
,它存在于 main
函数 中
def help(a, b)
:开始一个函数定义。在 help
函数中,您可以定义与 main
中的变量隔离的全新变量
print(res)
:打印变量 res
的值。要查找 res
的值,Python 将首先在 help
函数中查找名为 res
的变量。如果有 none,它将在 main
函数(即父作用域)中搜索名为 res
的变量。 (如果有none 那里,它会继续搜索越来越高的范围。)事实证明,在你的例子中,是否有一个变量在help
函数中命名为res
取决于第4行是否被注释掉!
res = min(res, a*b)
:这与您认为的不同。你想要它做的是改变main
函数中res
变量的变量值。但是,Python 将在 help
函数中创建一个 new 变量 res
并将其值设置为 min(res, a*b)
.
这就是您获得 UnboundLocalError
的原因。因为当第 4 行取消注释时,print(res)
指的是 help
函数中名为 res
的变量,而不是 main
函数。但是当第4行被注释掉时,help
函数中没有res
变量,所以print(res)
改用main
函数中的变量
那么,如何解决呢?其实很简单,把代码改成:
def help(a, b):
nonlocal res
print(res)
res = min(res, a*b)
nonlocal
语句告诉 Python,“嘿,res
变量来自外部作用域”。
我有代码:
def main(m):
res = m
def help(a, b):
print(res)
#res = min(res, a*b)
help(3,2)
return res
main(3)
代码有效。不过
def main(m):
res = m
def help(a, b):
print(res)
res = min(res, a*b)
help(3,2)
return res
main(3)
提高UnboundLocalError: local variable 'res' referenced before assignment
def main(m):
global res
res = m
def help(a, b):
print(res)
res = min(res, a*b)
help(3,2)
return res
main(3)
好像我加了global res
也没变。这里发生了什么?如何在函数 help
?
res
问题是您在 help()
函数中引入了一个新的、未初始化的局部变量,然后试图将其传递给 min(res, a*b)
函数。
您可以 return min(res, a*b)
并将其分配给 help()
函数之外的 res
,而不是尝试处理范围问题:
def main(m):
res = m
def help(a, b):
# print(res)
return min(res, a*b)
res = help(3,2)
return res
你需要告诉内部函数 res
变量是非本地的,像这样:
def main(m):
res = m
def help(a, b):
nonlocal res
print(res)
res = min(res, a*b)
help(3,2)
return res
main(3)
您可以在函数中读取非局部作用域变量而不会出现问题,但如果您尝试写入变量,则 python 假定您要创建一个新的局部作用域变量。该局部变量隐藏并阻止访问可能存在于更高范围的命名空间中的任何类似命名的变量,例如外部函数或全局变量。要通知它您不想创建局部变量并想访问外部范围变量,您需要使用 nonlocal
关键字,如上例所示。
使用 global res
无法修复它,因为全局变量位于命名空间层次结构的顶层,而您尝试访问的 res
变量不是。您要访问的 res
位于全局范围和本地范围之间。这就是为什么您需要使用 nonlocal
而不是 global
。如果 res
处于 top/external 级别,那么 global
就是解决方案。
这里的相关代码是
res = m
def help(a, b):
print(res)
res = min(res, a*b) # may or may not be commented out
这不是你想的那样。
让我们逐行分析一下:
res = m
:这定义了变量res
,值为m
,它存在于main
函数 中
def help(a, b)
:开始一个函数定义。在help
函数中,您可以定义与main
中的变量隔离的全新变量
print(res)
:打印变量res
的值。要查找res
的值,Python 将首先在help
函数中查找名为res
的变量。如果有 none,它将在main
函数(即父作用域)中搜索名为res
的变量。 (如果有none 那里,它会继续搜索越来越高的范围。)事实证明,在你的例子中,是否有一个变量在help
函数中命名为res
取决于第4行是否被注释掉!res = min(res, a*b)
:这与您认为的不同。你想要它做的是改变main
函数中res
变量的变量值。但是,Python 将在help
函数中创建一个 new 变量res
并将其值设置为min(res, a*b)
.
这就是您获得 UnboundLocalError
的原因。因为当第 4 行取消注释时,print(res)
指的是 help
函数中名为 res
的变量,而不是 main
函数。但是当第4行被注释掉时,help
函数中没有res
变量,所以print(res)
改用main
函数中的变量
那么,如何解决呢?其实很简单,把代码改成:
def help(a, b):
nonlocal res
print(res)
res = min(res, a*b)
nonlocal
语句告诉 Python,“嘿,res
变量来自外部作用域”。