我正在学习列表理解,我通过切换变量得到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先出现是否重要?
答案 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
循环以这种方式一起写入时(这次没有额外的括号),它们从左到右阅读。