0
点赞
收藏
分享

微信扫一扫

Python 列表推导

一. 使用列表推导,而不是 map 和 filter

列表推导不需要编写额外的 lambda 表达式,因此使用列表推导要比内置的 map filter 函数更加清晰。如下面的列子,同样是将一个列表中的元素取平方,返回一个新的列表:

>>> l = list(range(10))
>>> l
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> [i**2 for i in l]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

>>> list(map(lambda x: x**2, l))
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

此外,如果还需要对原列表中的元素进行过滤,那列表推导的优势将进一步体现,因为列表推导只需在循环后面添加条件表达式,即可直接过滤原列表的元素;而 map 则必选结合 filter 函数。如下面的例子,我们在求平方前需要过滤掉偶数项:

>>> [x** 2 for x in l if x%2 == 0]
[0, 4, 16, 36, 64]

>>> list(map(lambda x: x**2, filter(lambda x: x%2 == 0, l)))
[0, 4, 16, 36, 64]

最后,我们需要了解一下,除了列表推导,字典和集合也支持推导表达式:

>>> students = {1:'alex', 2:'bob', 3:'christian', 4:'dana', 5:'eartha'}
>>> students
{1: 'alex', 2: 'bob', 3: 'christian', 4: 'dana', 5: 'eartha'}

>>> {str(index*100)[::-1]:name.capitalize() for index, name in students.items()}
{'001': 'Alex',
 '002': 'Bob',
 '003': 'Christian',
 '004': 'Dana',
 '005': 'Eartha'}

>>> {len(name) for name in students.values()}
{3, 4, 6, 9}

二. 在列表推导中,请避免使用 2 个以上的表达式

列表推导除了上述的基本用法之外,还支持多重循环。如下面的例子,我们把二维矩阵简化为一维矩阵。先以 numpyndarray 说明目的:

>>> import numpy as np
>>> arr = np.arange(1,10).reshape(3,3)
>>> arr
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])
>>> arr.flatten()
array([1, 2, 3, 4, 5, 6, 7, 8, 9])

下面,我们将一个 2 维列表也像这样拉平成 1 维,采用包含 2 个 for 表达式的列表推导即可:

>>> my_list = arr.tolist()
>>> my_list
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> [x for row in my_list for x in row]
[1, 2, 3, 4, 5, 6, 7, 8, 9]

上面的例子简单易懂,下面再演示一种包含多重循环的合理用法,下面我们对 2 维列表中的每个元素求平方。 同样先以 numpy ndarray 来说明目的:

>>> arr**2
array([[ 1,  4,  9],
       [16, 25, 36],
       [49, 64, 81]], dtype=int32)

ndarray 可以直接进行矢量运算,非常简单。因为还是只包含 2 个循环,所以列表的实现也不复杂,很容易理解:

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

列表推导也支持多个 if 条件,处在同一循环级别中的多项条件,彼此之间默认形成 and 表达式。比如下面的例子,从列表中选出大于 5 的偶数:

>>> my_list = list(range(1,10))
>>> my_list
[1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> [x for x in my_list if x > 5 and x % 2 == 0 ]
[6, 8]

>>> [x for x in my_list if x > 5 if x % 2 == 0 ]
[6, 8]

比如,下面的例子,就非常的复杂,阅读代码的其他人很难理解。这里只列出演示过程,就不具体讲解啦,有兴趣的同学可以自己推敲一下,但请不要在你的项目中写出如此复杂的列表推导,会增加后期其他开发人员的维护成本。

>>> arr
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])
>>> my_arr = arr[np.newaxis,:]
>>> my_arr
array([[[1, 2, 3],
        [4, 5, 6],
        [7, 8, 9]]])

>>> my_list = my_arr.tolist()
>>> my_list
[[[1, 2, 3], [4, 5, 6], [7, 8, 9]]]
>>> flat = [x for sublist1 in my_list for sublist2 in sublist1 for x in sublist2]
>>> flat
[1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> my_list_2 = arr.tolist()
>>> my_list_2
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> filtered = [[x ** 2 for x in row if x % 3 == 0] for row in my_list_2 if sum(row) > 10]
>>> filtered
[[36], [81]]
举报

相关推荐

0 条评论