【问题标题】:Python List comprehension execution order [duplicate]Python列表理解执行顺序[重复]
【发布时间】:2019-07-13 21:36:29
【问题描述】:
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
squared = [[x**2 for x in row] for row in matrix]
print(squared)

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

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

【问题讨论】:

  • 与原列表顺序一致

标签: python list-comprehension


【解决方案1】:

元素顺序

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

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

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

但在你的情况下,你有两个列表推导,每个都有一个块:

  • 外部列表理解:为matrix 中的每个row 做一些事情;
  • 内部列表理解(用row 做某事):为row 中的每个x 做其他事情。

这就是为什么你的列表理解最好从右到左阅读。 使用函数更容易看到:

>>> 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]

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

执行顺序

这就是你问的问题,即使我不确定这是你想问的问题!操作按什么顺序执行?规范似乎对这个问题没有任何说明,但答案是:没关系,只要您避免列表推导中的副作用。如果您从列表推导式中得到一个列表(不引发异常),则无论它是如何构建的,都可以保证完成此列表。

但如果您不遵循“无副作用”的规则,则执行副作用的顺序可能会改变最终结果。 你可以使用一个技巧来测试它: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]]

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      在 Python 中的列表推导 执行:

      for item in lista:
          item * 2
      

      等于:

      [item * 2 for item in lista]
      

      【讨论】:

      • 它们既不相等也不等价:第一个for循环遍历元素并将它们平方而不存储任何地方,第二个循环从平方元素构造list
      猜你喜欢
      • 1970-01-01
      • 2021-05-02
      • 1970-01-01
      • 2017-07-12
      • 2011-06-15
      • 2012-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多