重构过滤器并映射到列表推导
filter
或 map
函数通常应该由列表推导替换。Guido Van Rossum 在 2005 年的一封公开信中描述了这一点 :
filter(P, S)
几乎总是像[x for x in S if
P(x)]
一样更加清晰,这有一个巨大的优势,即最常见的用法涉及比较的谓词,例如x==42
,并且定义一个 lambda,这对读者来说需要更多的努力(加上 lambda 比列表理解)。对于map(F, S)
来说更是如此。当然,在许多情况下,你可以使用生成器表达式。
以下代码行被认为是“ 非 pythonic ”,并且会在许多 python linters 中引发错误。
filter(lambda x: x % 2 == 0, range(10)) # even numbers < 10
map(lambda x: 2*x, range(10)) # multiply each number by two
reduce(lambda x,y: x+y, range(10)) # sum of all elements in list
根据我们从前面的引文中学到的东西,我们可以将这些 filter
和 map
表达式分解为它们的等效列表推导 ; 还从每个函数中删除 lambda 函数 - 使代码在此过程中更具可读性。
# Filter:
# P(x) = x % 2 == 0
# S = range(10)
[x for x in range(10) if x % 2 == 0]
# Map
# F(x) = 2*x
# S = range(10)
[2*x for x in range(10)]
在处理链接函数时,可读性变得更加明显。由于可读性,一个映射或过滤函数的结果应该作为结果传递给下一个; 在简单的情况下,这些可以用单个列表理解来代替。此外,我们可以很容易地从列表中了解我们的过程的结果是什么,在推断链式 Map 和 Filter 过程时有更多的认知负荷。
# Map & Filter
filtered = filter(lambda x: x % 2 == 0, range(10))
results = map(lambda x: 2*x, filtered)
# List comprehension
results = [2*x for x in range(10) if x % 2 == 0]
重构 - 快速参考
-
地图
map(F, S) == [F(x) for x in S]
-
过滤
filter(P, S) == [x for x in S if P(x)]
其中 F
和 P
是分别转换输入值并返回 bool
的函数