微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

赋值前引用的局部变量 - Python

如何解决赋值前引用的局部变量 - 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+ENTERx 作为循环变量告诉解释器这些是局部变量。但是,yrange(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 在他的评论中指出的,您在列表理解中使用了 xy «用于两个相互矛盾的目的»。您需要在 for 循环中为每个人赋予唯一的名称,例如y -> k

进一步查看 at this SO post 以了解有关嵌套列表推导式的更多信息。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?