python - Python内部函数变量范围
问题描述
我在编写的关于变量范围的内部函数时遇到了问题。我已经设法简化代码以指出确切的问题。所以开始:
def outer(foo):
def inner(bar):
print(foo)
print(bar)
return inner
if __name__ == "__main__":
function = outer("foo")
function("bar")
我将得到预期的输出:
foo
bar
但是,如果我尝试重新分配 foo,则会收到错误消息:
def outer(foo):
def inner(bar):
foo = "edited " + foo
print(foo)
print(bar)
return inner
这使:
UnboundLocalError: local variable 'foo' referenced before assignment
这让我想起了全局变量,您可以在其中正常“读取”它们,但要“写入”您必须执行“全局变量;变量 =...”。是不是一样的情况?如果是这样,是否有允许从内部修改 foo 的关键字?还有为什么?当然,一旦我创建了函数,那么 foo 就为该函数固定了。即不是全球性的。这里要避免什么问题?
解决方案
[...] 是否有允许从内部修改 foo 的关键字?
确实有这样一个关键词:nonlocal
def outer(foo):
def inner(bar):
nonlocal foo
foo = "edited " + foo
print(foo)
print(bar)
return inner
outer("foo")("bar")
输出:
edited foo
bar
从文档:
nonlocal_stmt ::= "nonlocal" 标识符 ("," 标识符)*
nonlocal 语句导致列出的标识符引用最近的封闭范围内的先前绑定的变量,不包括全局变量。这很重要,因为绑定的默认行为是首先搜索本地命名空间。该语句允许封装代码重新绑定全局(模块)范围之外的局部范围之外的变量。
与 global 语句中列出的名称不同,在 nonlocal 语句中列出的名称必须引用封闭范围中的预先存在的绑定(无法明确确定应创建新绑定的范围)。
非本地语句中列出的名称不得与本地范围内的预先存在的绑定发生冲突。
至于why
部分:
代码块中的任何赋值 (x = y) 都会将变量的范围更改为当前范围。因此,要从全局范围引用和修改 (*) 变量,我们需要关键字global
,但在这种情况下,我们需要来自“最近封闭”范围的变量,因此我们需要关键字nonlocal
。
(*) 通过赋值修改;可变全局变量仍然可以使用它们各自的方法修改,而无需 global/nonlocal 关键字。
推荐阅读
- vuejs2 - Laravel 在我的 VueJS + JWT 驱动的系统中报告了 400(错误请求;未提供令牌)
- jquery - Sonata-Admin 中的 JQuery 冲突(在 Symfony 4 项目中)
- rx-java - 在嵌套循环 + vert.x + rx 的情况下应如何处理结果处理程序
- javascript - 从 Jest 中的另一个函数调用模拟函数
- excel - vba excel listobject HeaderRowRange
- tensorflow - 将 .npy 输入到 tensorflow 数据管道中
- azure - Azure & Powershell:Get-AzureRmDeletedWebApp 抛出奇怪的错误
- rest - 具有不同请求集的 REST API POST/PUT
- azure - ng build --prod on Azure 致命错误:CALL_AND_RETRY_LAST 分配失败 - JavaScript 堆内存不足
- angular - Angular 5 - 动态基础引用导致重复加载包|块