编写高质量Python (第27条) 用列表推导取代 map 与filter

第27条 用列表推导取代 map 与filter

​ Python 里面有一种很精简的写法,可以根据某个序列或可迭代对象派生出一份新的列表。用这种写法写成的表达式,叫做列表推导(list comprehension)。 假如我们要使用列表中每个元素的平方值构造一份新的列表。传统的写法是,采用下面这个简单的 for 循环实现。

a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
square = []
for x in a:
    square.append(x ** 2)
print(square)


>>>
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

​ 上面那段代码可以改用列表推导来写,这样可以在迭代列表的过程中,根据表达式酸楚新列表的对应元素。

square = [x ** 2 for x in a]  # List comprehension
print(square)

>>>
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

​ 这种功能当然也可以用内置函数 map 实现,它能够从多个列表中分别取出当前位置上的元素,并把它们当成参数传给映射函数,以求出新列表在这个位置上的元素值。如果映射关系比较简单(假如只是把一个列表映射到另一个列表),那么用列表推导来写还是比用 map 简单一些,因为用 map 的时候,必须先把映射逻辑定义为 lambda 函数,这看上去稍微有点繁琐。

alt = map(lambda x: x ** 2, a)

​ 列表推导还有一个地方比 map 好,就是它能够方便地过滤原列表,把某些输入值对应的计算结果从输出结果中排除。例如,假设新列表只需要纳入原列表中的那些偶数的平方值,那我们可以在推导的时候,在 for x in a 这一部分的右侧写一个条件表达式:

even_squares = [x ** 2 for x in a if x % 2 == 0]
print(even_squares)

>>>
[4, 16, 36, 64, 100]

​ 这种功能也可以通过内置的 filter 与 map 函数来实现,但是这两个函数相结合的写法要比列表推导难懂一些。

alt = map(lambda x: x**2, filter(lambda x: x % 2 == 0, a))
assert even_squares == list(alt)

字典和集合也有相应的推导机制,分别叫做字典推导(dictionary comprehension) 和集合推导(set comprehension)。 编写算法时,可以利用这些机制根据原字典与原集合创建新字典和新集合。

a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_square_dict = {x: x ** 2 for x in a if x % 2 == 0}
threes_cubed_set = {x ** 3 for x in a if x % 3 == 0}
print(even_square_dict)
print(threes_cubed_set)

>>>
{2: 4, 4: 16, 6: 36, 8: 64, 10: 100}
{216, 729, 27}

​ 如果改用 map 与 filter 实现,那么还必须调用相应的构造器(constructor),这会让代码变得很长,需要分多行才能写得下。这样看起来比较乱,不如使用推导机制的代码清晰。

alt_dict = dict(map(lambda x: (x, x ** 2),
								filter(lambda x: x % 2 == 0, a)))
alt_set = set(map(lambda x: x ** 3,
							filter(lambda x: x % 3 == 0, a)))
  • 9
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值