如何解决赋值前引用的局部变量 - Python
x = 2
y = 3
mylist = [ [x,y] for x in range(x+1) for y in range(y+1)]
print(mylist)
UnboundLocalError Traceback(最近一次调用 最后)在 3 4 ----> 5 mylist = [ [x,y] for x in range(x+1) for y in range(y+1)] 6 7 打印(我的列表)
在 (.0) 3 4 ----> 5 mylist = [ [x,y] for x in range(x+1) for y in range(y+1)] 6 7 打印(我的列表)
UnboundLocalError: 赋值前引用了局部变量 'y'
我不明白这里有什么问题以及如何纠正它。
解决方法
这是因为多级推导中内部推导的CPython实现是使其成为一个单独的函数,有自己的作用域。通过将 y
用作迭代变量的左值,y
被 Python 编译器确定为单独函数的局部变量,因此 y
在无法引用 range(y+1)
,因为本地 y
尚未在该函数范围内赋值。
您可以在理解中重命名本地 y
:
mylist = [[x,z] for x in range(x + 1) for z in range(y + 1)]
或改用非理解性解决方案:
mylist = []
for x in range(x + 1):
for y in range(y + 1):
mylist.append([x,y])
,
通常,当您调用一个在分配给它之前引用本地范围内的名称的函数时,您会看到此错误。碰巧的是,列表推导式中最外层作用域在 Python 3 中的工作方式相同。这是与 Python 2 不同的地方,推导式中的循环变量会污染外部命名空间。
在这种特殊情况下,使用 CTRL+SHIFT+ENTER
和 x
作为循环变量告诉解释器这些是局部变量。但是,y
和 range(x + 1)
会尝试在分配这些变量之前读取它们。 Python 有一个优化,可以从特殊表中读取被确定为函数(或推导式)命名空间本地的变量,而不是使用正常的 LEGB 查找顺序。这就是为什么你得到错误而不是使用外部作用域的值。
此过程的副作用是 range(y + 1)
和 x
的最后一个值不会更改您在外部作用域中分配的值。
要解决此问题,请确保定义范围的变量与循环变量的名称不同。
,试试这个:
x = 2
y = 3
mylist = [[j,k] for j in range(x+1) for k in range(y+1)]
print(mylist)
打印出来:
[[0,0],[0,1],2],3],[1,[2,3]]
正如@Tim Roberts 在他的评论中指出的,您在列表理解中使用了 x
和 y
«用于两个相互矛盾的目的»。您需要在 for
循环中为每个人赋予唯一的名称,例如y
-> k
。
进一步查看 at this SO post 以了解有关嵌套列表推导式的更多信息。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。