5.1.3. 列表推导式

列表推导式提供了一个更简单的创建列表的方法。常见的用法是把某种操作应用于序列或可迭代对象的每个元素上,然后使用其结果来创建列表,或者通过满足某些特定条件元素来创建子序列。

例如,假设我们想创建一个平方列表,像这样

  1. >>> squares = []
  2. >>> for x in range(10):
  3. ... squares.append(x**2)
  4. ...
  5. >>> squares
  6. [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

注意这里创建(或被重写)的名为 x 的变量在for循环后仍然存在。我们可以计算平方列表的值而不会产生任何副作用

  1. squares = list(map(lambda x: x**2, range(10)))

或者,等价于

  1. squares = [x**2 for x in range(10)]

上面这种写法更加简洁易读。

列表推导式的结构是由一对方括号所包含的以下内容:一个表达式,后面跟一个 for 子句,然后是零个或多个 forif 子句。 其结果将是一个新列表,由对表达式依据后面的 forif 子句的内容进行求值计算而得出。 举例来说,以下列表推导式会将两个列表中不相等的元素组合起来:

  1. >>> [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
  2. [(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

而它等价于

  1. >>> combs = []
  2. >>> for x in [1,2,3]:
  3. ... for y in [3,1,4]:
  4. ... if x != y:
  5. ... combs.append((x, y))
  6. ...
  7. >>> combs
  8. [(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

注意在上面两个代码片段中, forif 的顺序是相同的。

如果表达式是一个元组(例如上面的 (x, y)),那么就必须加上括号

  1. >>> vec = [-4, -2, 0, 2, 4]
  2. >>> # create a new list with the values doubled
  3. >>> [x*2 for x in vec]
  4. [-8, -4, 0, 4, 8]
  5. >>> # filter the list to exclude negative numbers
  6. >>> [x for x in vec if x >= 0]
  7. [0, 2, 4]
  8. >>> # apply a function to all the elements
  9. >>> [abs(x) for x in vec]
  10. [4, 2, 0, 2, 4]
  11. >>> # call a method on each element
  12. >>> freshfruit = [' banana', ' loganberry ', 'passion fruit ']
  13. >>> [weapon.strip() for weapon in freshfruit]
  14. ['banana', 'loganberry', 'passion fruit']
  15. >>> # create a list of 2-tuples like (number, square)
  16. >>> [(x, x**2) for x in range(6)]
  17. [(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25)]
  18. >>> # the tuple must be parenthesized, otherwise an error is raised
  19. >>> [x, x**2 for x in range(6)]
  20. File "<stdin>", line 1, in <module>
  21. [x, x**2 for x in range(6)]
  22. ^
  23. SyntaxError: invalid syntax
  24. >>> # flatten a list using a listcomp with two 'for'
  25. >>> vec = [[1,2,3], [4,5,6], [7,8,9]]
  26. >>> [num for elem in vec for num in elem]
  27. [1, 2, 3, 4, 5, 6, 7, 8, 9]

列表推导式可以使用复杂的表达式和嵌套函数

  1. >>> from math import pi
  2. >>> [str(round(pi, i)) for i in range(1, 6)]
  3. ['3.1', '3.14', '3.142', '3.1416', '3.14159']