Python List理解执行顺序

时间:2019-07-13 21:36:29

标签: python list-comprehension

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
squared = [[x**2 for x in row] for row in matrix]
print(squared)

在前面的数据结构和列表理解中,执行的顺序是什么?

从视觉上看,它似乎是从右到左处理。考虑到嵌套列表首先必须是可访问的,然后才能对每个单独的项目进行平方。

3 个答案:

答案 0 :(得分:1)

元素顺序

PEP 202不够全面,但是您可以在Python Language Reference中找到一些信息:

  

理解由单个表达式组成,后跟至少一个for子句和零个或多个for或if子句。在这种情况下,新容器的元素是通过将每个for或if子句视为一个块,从左向右嵌套,并在每次到达最内层的块时评估表达式以产生一个元素而产生的元素。   [...]   最左边的for子句中的可迭代表达式在封闭范围内直接求值,然后作为参数传递给隐式嵌套范围。

因此列表理解从左到右进行for个块。

但是在您的情况下,您有两个列表理解,每个列表理解一个块:

  • 外部列表理解:为row中的每个matrix做些事情;
  • 内部列表理解(对row进行操作):对x中的每个row做其他操作。

这就是为什么从右到左更好地理解列表的原因。 使用函数更容易看到:

>>> def square_elements(row): return [x**2 for x in row] # inner
...
>>> matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> [square_elements(row) for row in matrix] # outer
[[1, 4, 9], [16, 25, 36], [49, 64, 81]]

现在考虑两个阻止列表:

>>> [x**2 for row in matrix for x in row]
[1, 4, 9, 16, 25, 36, 49, 64, 81]

您会看到从左到右的顺序。在第一种情况下,您必须:row中的每个matrix做某事,而要做的是:为x中的每个row做其他事。在第二种情况下,它是:x 中每个row的每个matrix做某事。

执行顺序

这是您提出的问题,即使我不确定这是您想提出的问题!该操作以什么顺序执行?规范似乎没有对这个问题说什么,但答案是:没关系,只要您避免列表理解中的副作用即可。如果您从列表理解中获得列表(不引发异常),则无论列表如何构建,都可以保证该列表是完整的。

但是,如果您不遵循“无副作用”规则,则执行副作用的顺序可能会更改最终结果。 您可以使用一种技巧对其进行测试:print函数返回None,因此if not print(...)始终为True

>>> matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> squared = [[x**2 for x in row if not print("value", x)] for row in matrix if not print("row", row)]
row [1, 2, 3]
value 1
value 2
value 3
row [4, 5, 6]
value 4
value 5
value 6
row [7, 8, 9]
value 7
value 8
value 9
>>> squared
[[1, 4, 9], [16, 25, 36], [49, 64, 81]]

顺序似乎是“自然的”,但我不认为您应该依赖它(更重要的是:列表理解中不应有副作用)。

答案 1 :(得分:0)

顺序是从左到右。那就是第一行的所有行元素都将首先平方。

答案 2 :(得分:0)

在Python中的列表理解 执行:

for item in lista:
    item * 2

等于:

[item * 2 for item in lista]