重新排序列表推导中的语句时的NameError

时间:2016-09-30 06:45:41

标签: python list

我正在学习列表理解,我通过切换变量得到2个不同的结果,虽然它们看起来应该是相同的。

数组a等于[[0, 0, 0, 0, 0], [1, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]

列表理解1作品:

[(i,j) for j in range(len(a[i])) for i in range(len(a))] 

返回:

[(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (0, 1), (1, 1), (2, 1), (3, 1), (4, 1), (0, 2), (1, 2), (2, 2), (3, 2), (4, 2), (0, 3), (1, 3), (2, 3), (3, 3), (4, 3), (0, 4), (1, 4), (2, 4), (3, 4), (4, 4)]

正如所料。

但是翻转变量......

[(j,i) for i in range(len(a[j])) for j in range(len(a))]

NameError中的结果:未定义名称“j”

有人可以向我解释为什么我或者j先出现是否重要?

2 个答案:

答案 0 :(得分:6)

当您在单个列表理解中有一个双for循环时,它相当于使用"传统"以相同的顺序执行那些for循环。 for循环。所以

result = [(j,i) for i in range(len(a[j])) for j in range(len(a))]

(几乎完全)等同于

result = []
for i in range(len(a[j])):
    for j in range(len(a)):
        result.append((j, i))

正如您所看到的,当您执行len(a[j])时,变量j不存在,这就是您获得NameError的原因。

顺便说一下,你的第一个列表组合也不应该工作。我怀疑您之前已在代码中定义了i,这就是为什么您没有获得NameError。这是该列表组件的略微改进版本,它假设a是一个矩阵,即它的所有子列表长度相同,并且它至少包含一个子列表。

[(i,j) for j in range(len(a[0])) for i in range(len(a))]

我们也可以

[(j, i) for i in range(len(a)) for j in range(len(a[0]))]

这两个列表组合都创建了这个列表:

[(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (0, 1), (1, 1), (2, 1), (3, 1), (4, 1), (0, 2), (1, 2), (2, 2), (3, 2), (4, 2), (0, 3), (1, 3), (2, 3), (3, 3), (4, 3), (0, 4), (1, 4), (2, 4), (3, 4), (4, 4)]

答案 1 :(得分:4)

这里不重要的变量顺序。实际上,运行List Comprehension 1也不起作用,原因与List Comprehension 2相同。我猜你在程序的早期定义了i,这就是List Comprehension 1为你工作的原因。问题是for循环的顺序。

我会试着通过例子来解释。如果你这样写它,它会运行良好:

[ [(i,j) for j in range(len(a[i]))] for i in range(len(a))] 

请注意我添加的方括号。在这种情况下,首先发生for循环i,然后for循环j。 (但应该注意,这将返回元组列表的列表。)或者,这也可以正常运行:

[(i,j) for i in range(len(a)) for j in range(len(a[i]))] 

当两个for循环以这种方式一起写入时(这次没有额外的括号),它们从左到右阅读。