Python map, filter, reduce 函数的注意事项

介绍

注意:本文所说的 python 都是指 python3,python2 已不再被支持 :)

map(), filter() 以及 reduce() 是 Python 中与函数式编程相关的三个函数,可以对可迭代序列做映射,过滤以及累积。熟练使用这三个函数可以提升编码速度,并且感受到函数式编程的一些思想。但是在使用过程中需要注意一些事项

TL;DR

  1. from functools import reduce.
  2. 返回对象,map, filter 返回可迭代对象,对象操作是惰性的

使用方法

map 与 filter 做为内置函数,可以直接使用,如:

1
2
3
4
5
6
7
8
9
a = [1,2,3]
b = list(map(lambda x: x+1, a))
c = list(filter(lambda x : x % 2 == 0, a))
print(b)
print(c)

# output
# [2, 3, 4]
# [2]

而 reduce() 函数的使用则需要从 functools 包中导入, 如:

1
2
3
4
5
6
7
from functools import reduce

a = [1, 2, 3, 4]
reduce(lambda x, y : x+y, a)

# output
# 10

同时,reduce() 中传入的函数的参数数量为两个。

返回值

reduce 返回累积后的值,而 map 与 filter 返回的是可迭代的对象,分别为 map object 和 filter object。

1
2
3
4
5
6
7
8
9
10
11
a = [1, 2, 3]

b = map(lambda x: x + 1, a)
print(b)

c = filter(lambda x: x % 2 != 0, a)
print(c)

# output:
# <map object at 0xXXXXX>
# <filter object at 0xXXXXXXX>

map, filter 传入的函数,只有在返回的可迭代对象被消费时才会实际调用,即惰性求值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def test(a):
print("evaluation")
return a + 1

a = [1, 2, 3]

b = map(test, a)
print("not evaluation")
print(list(b)) # evaluation here because of list()

# output:
# not evaluation
# evaluation
# evaluation
# evaluation
# [2, 3, 4]


由于返回的是一个可迭代对象,因此所有的值只能迭代一次,再次尝试迭代,将会返回一个空集,如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
a = [1, 2, 3]

a = [1, 2, 3]

b = map(lambda x : x + 1, a)
a = [1, 2, 3]

b = list(map(lambda x : x + 1, a))
print("First iteration")
[print(i) for i in b]
print("Second iteration")
[print(i) for i in b]

# output:
# First iteration
# 2
# 3
# 4
# Second iteration

因此,在如果需要多次使用返回的迭代对象,可以通过调用 list() 方法将其转化为一个 list 对象,之后使用生成的 list 对象即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
a = [1, 2, 3]

b = list(map(lambda x : x + 1, a))
print("First iteration")
[print(i) for i in b]
print("Second iteration")
[print(i) for i in b]

# output:
# First iteration
# 2
# 3
# 4
# Second iteration
# 2
# 3
# 4

Python map, filter, reduce 函数的注意事项
https://blog.zhangliangliang.cc/post/undefined.html
作者
Bobby Zhang
发布于
2020年5月6日
许可协议