lambda:一次性小函数

square = lambda x: x ** 2
square(5)        # 25

# 等价于
def square(x):
    return x ** 2

只能写一个表达式,不能有 if/for/return主要用作高阶函数的参数

nums = [1, 2, 3, 4, 5]
nums.sort(key=lambda x: -x)         # 按相反数排,等于降序
filter(lambda x: x % 2 == 0, nums)

map:把函数应用到每个元素

list(map(str.upper, ["hello", "world"]))
# ['HELLO', 'WORLD']

list(map(lambda x: x ** 2, [1, 2, 3, 4]))
# [1, 4, 9, 16]

filter:保留满足条件的

list(filter(lambda x: x > 0, [-2, -1, 0, 1, 2]))
# [1, 2]

list(filter(None, [0, 1, "", "a", None, []]))
# [1, 'a']    None 表示"过滤掉假值"

reduce:累计

from functools import reduce

reduce(lambda a, b: a + b, [1, 2, 3, 4])
# 10  ((1+2)+3)+4

reduce(lambda a, b: a * b, [1, 2, 3, 4])
# 24

reduce(lambda a, b: a + b, [1, 2, 3, 4], 100)
# 110  初始值 100

Python 的取舍:推导式 vs map/filter

很多 Pythonista 更喜欢推导式:

# map / filter
list(map(lambda x: x ** 2, filter(lambda x: x > 0, nums)))

# 推导式(更易读)
[x ** 2 for x in nums if x > 0]

推导式赢——它更 Python

map / filter 仍然有用的场景

  1. 方法引用(不需要写 lambda):

    list(map(str.strip, lines))    # 比 [s.strip() for s in lines] 略简
    
  2. 配合其他高阶函数

    from itertools import accumulate
    list(accumulate(map(int, "12345"), lambda a, b: a + b))
    
  3. 流式处理大数据(map 返回迭代器,懒加载):

    for line in map(str.strip, open("huge.txt")):
        process(line)
    

any / all:常被忘记的好东西

any(x > 0 for x in nums)        # 有任意一个正数?
all(x > 0 for x in nums)        # 全都是正数?

# 替代 for 找"有没有匹配"
any("error" in line for line in log_lines)

一条经验

写函数式 ≠ 写好代码。Python 不是 Haskell——什么用着舒服用什么。推导式 / 普通 for / map 都是工具,按场景选。

下一篇讲 functools 全家桶——partial / lru_cache 才是函数式在 Python 里最实用的部分。