🎮 Python函数式编程:让你的代码像打游戏一样爽!

23 阅读21分钟

副标题:老板再也不用担心我的代码写成一坨💩了!


📖 目录

  1. 开篇:函数式编程是啥玩意儿?
  2. 核心概念:六大天王登场!
  3. Python武器库:内置函数式工具
  4. 实战演练:从生活到代码
  5. 进阶技巧:装逼必备
  6. 总结:函数式编程的正确打开方式

🎯 开篇:函数式编程是啥玩意儿?

先说个故事 📚

想象你是一家奶茶店的老板(恭喜发财!💰),每天要处理很多订单:

顾客A:我要一杯珍珠奶茶,三分糖,少冰
顾客B:我要一杯芝士奶盖,五分糖,正常冰
顾客C:我要一杯柠檬茶,无糖,多冰

你有两种做法:

🤪 传统方式(命令式编程)

# 就像你亲自做每一杯奶茶,手忙脚乱
def make_tea_traditional():
    tea = "茉莉绿茶"  # 先准备茶底
    tea = tea + "珍珠"  # 加珍珠
    tea = tea + "三分糖"  # 加糖
    tea = tea + "少冰"  # 加冰
    return tea
    
# 结果:你累得像条狗 🐶

😎 函数式方式(函数式编程)

# 就像你设计了一套流水线,每个员工只负责一个步骤
def add_pearl(tea):
    return tea + "珍珠"

def add_sugar(tea, level):
    return tea + f"{level}分糖"

def add_ice(tea, amount):
    return tea + f"{amount}冰"

# 组装流水线!
def make_tea_functional(base_tea, sugar_level, ice_amount):
    return add_ice(add_sugar(add_pearl(base_tea), sugar_level), ice_amount)

result = make_tea_functional("茉莉绿茶", "三", "少")
# 结果:你坐着数钱 💰

💡 一句话总结

函数式编程 = 把大问题拆成小函数 + 像搭乐高一样组合它们

┌─────────────────────────────────────┐
│  传统编程:我做 ➜ 我做 ➜ 我做 😓    │
│  函数式编程:你做 ➜ 他做 ➜ 她做 😌  │
└─────────────────────────────────────┘

🌟 核心概念:六大天王登场!

1️⃣ 纯函数(Pure Function):最靠谱的朋友 🤝

什么是纯函数?

就像你有个朋友,每次你问他"1+1等于几?",他都会回答"2"。他不会:

  • ❌ 今天说2,明天说3
  • ❌ 偷偷把你的钱包藏起来
  • ❌ 给你的答案同时改变世界

这就是纯函数

特点:
  1. 相同输入 ➜ 相同输出(可预测)
  2. 没有副作用(不搞事情)
代码示例:
# ✅ 纯函数:好朋友
def add(a, b):
    return a + b

print(add(3, 5))  # 永远是 8
print(add(3, 5))  # 还是 8
print(add(3, 5))  # 依然是 8,靠谱!

# ❌ 不纯函数:坏朋友
total = 0

def add_to_total(x):
    global total
    total += x  # 偷偷改了全局变量!
    return total

print(add_to_total(5))  # 5
print(add_to_total(5))  # 10(咦?怎么变了?)
print(add_to_total(5))  # 15(妈呀!完全不靠谱!)
生活比喻:🍔
纯函数 = 自动贩卖机
- 投币1元 ➜ 掉出可乐 ✅
- 投币1元 ➜ 掉出可乐 ✅
- 投币1元 ➜ 掉出可乐 ✅
(每次都一样,靠谱!)

不纯函数 = 盲盒机
- 投币1元 ➜ 掉出玩偶 🎁
- 投币1元 ➜ 掉出石头 🪨
- 投币1元 ➜ 啥都没有 💸
(完全看心情,玄学!)

2️⃣ 高阶函数(Higher-Order Function):函数界的VIP 👑

什么是高阶函数?

把函数当成"一等公民",可以:

  • 📥 作为参数传递
  • 📤 作为返回值返回
  • 📦 赋值给变量

就像你的朋友不仅能干活,还能指挥别人干活!

代码示例:
# 🎭 场景:你是个派对策划师
def apply_operation(func, x, y):
    """
    func: 一个函数(员工)
    x, y: 参数(材料)
    """
    print(f"📢 老板说:用 {func.__name__} 处理 {x}{y}")
    return func(x, y)

def add(a, b):
    return a + b

def multiply(a, b):
    return a * b

# 你今天想加法
result1 = apply_operation(add, 5, 3)  # 8
print(f"✅ 结果:{result1}")

# 你明天想乘法
result2 = apply_operation(multiply, 5, 3)  # 15
print(f"✅ 结果:{result2}")

输出:

📢 老板说:用 add 处理 53
✅ 结果:8
📢 老板说:用 multiply 处理 53
✅ 结果:15
生活比喻:🚗
普通函数 = 汽车
- 你开车去上班 🚗

高阶函数 = 代驾司机
- 你告诉司机:"去机场"(传入目的地)
- 司机开你的车(函数)去机场
- 你坐在后座睡觉 😴(解放双手!)
图解:
┌──────────────────────────────┐
│  高阶函数 apply_operation    │
│  ┌────────────────────────┐  │
│  │  接收函数 func         │  │
│  │  ⬇                    │  │
│  │  执行 func(x, y)      │  │
│  │  ⬇                    │  │
│  │  返回结果             │  │
│  └────────────────────────┘  │
└──────────────────────────────┘

3️⃣ 不可变性(Immutability):穿越时空的照片 📸

什么是不可变性?

数据一旦创建,就不能改变。想改?那就复制一份新的!

就像:

  • ✅ 照片拍完就不能改,只能P图生成新照片
  • ❌ 不像橡皮泥,可以随便捏
为什么要不可变?

防止你的数据被"神秘力量"改掉!

# ❌ 可变数据:恐怖故事
my_list = [1, 2, 3]
your_list = my_list  # 你以为复制了?

your_list.append(4)  # 你改了你的列表

print(my_list)   # [1, 2, 3, 4] 😱 我的列表也变了?!
print(your_list) # [1, 2, 3, 4]

# ✅ 不可变数据:温馨故事
my_tuple = (1, 2, 3)
your_tuple = my_tuple + (4,)  # 创建新的

print(my_tuple)   # (1, 2, 3) ✅ 我的没变
print(your_tuple) # (1, 2, 3, 4) ✅ 你的是新的
生活比喻:🎨
可变数据 = 沙雕
- 你堆了个城堡 🏰
- 风一吹...没了 💨
- 或者被熊孩子踢烂了 👶

不可变数据 = 雕塑
- 你雕了个城堡 🗿
- 风吹雨打都不怕
- 想改?重新雕一个!

4️⃣ Lambda 表达式:快餐式函数 🍔

什么是 Lambda?

一次性使用的小函数,不需要名字(匿名函数)。

就像:

  • 🍜 普通函数 = 大餐(精心准备)
  • 🍔 Lambda = 快餐(拿了就走)
语法:
lambda 参数: 返回值
代码示例:
# 🎯 普通函数:正式场合
def square(x):
    return x ** 2

result1 = square(5)  # 25

# ⚡ Lambda:快速场合
square_lambda = lambda x: x ** 2
result2 = square_lambda(5)  # 25

# 🚀 直接使用(更常见)
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x ** 2, numbers))
print(squared)  # [1, 4, 9, 16, 25]
什么时候用 Lambda?
# ✅ 适合用 Lambda:简单操作
sorted_list = sorted([3, 1, 4, 1, 5], key=lambda x: -x)

# ❌ 不适合用 Lambda:复杂逻辑
# 这样写就太蠢了...
is_valid = lambda user: user['age'] >= 18 and user['has_id'] and not user['is_blocked'] and user['country'] == 'China'

# 应该用普通函数!
def is_valid_user(user):
    if user['age'] < 18:
        return False
    if not user['has_id']:
        return False
    if user['is_blocked']:
        return False
    if user['country'] != 'China':
        return False
    return True
生活比喻:📝
普通函数 = 正式合同
- 签名
- 盖章
- 留底
- 存档

Lambda = 便利贴
- 写个提醒
- 看完就扔
- 简单快速

5️⃣ 闭包(Closure):函数的私人保险箱 🔐

什么是闭包?

一个函数"记住"了它创建时的环境(变量)。

就像你的日记本,只有你能看到里面的秘密!

代码示例:
# 🏦 场景:银行账户
def create_account(initial_balance):
    """创建一个账户"""
    balance = initial_balance  # 这是私有变量!
    
    def deposit(amount):
        """存钱"""
        nonlocal balance
        balance += amount
        return f"存入 {amount}元,余额:{balance}元 💰"
    
    def withdraw(amount):
        """取钱"""
        nonlocal balance
        if amount > balance:
            return "余额不足!穷鬼!😭"
        balance -= amount
        return f"取出 {amount}元,余额:{balance}元 💸"
    
    def get_balance():
        """查询余额"""
        return f"当前余额:{balance}元 🏦"
    
    return {
        'deposit': deposit,
        'withdraw': withdraw,
        'get_balance': get_balance
    }

# 🎉 创建两个账户
account1 = create_account(1000)
account2 = create_account(5000)

print(account1['get_balance']())  # 当前余额:1000元
print(account1['deposit'](500))   # 存入 500元,余额:1500元
print(account1['withdraw'](200))  # 取出 200元,余额:1300元

print(account2['get_balance']())  # 当前余额:5000元(不受影响!)
为什么牛逼?
  • ✅ 数据隐藏:外部无法直接访问 balance
  • ✅ 状态保持:每个账户有自己的 balance
  • ✅ 安全可靠:不会被其他代码污染
生活比喻:🗝️
闭包 = 保险箱
┌────────────────────────┐
│  🔐 保险箱(函数)      │
│  ┌──────────────────┐  │
│  │ 💰 金币(变量)   │  │
│  │ 💎 宝石(变量)   │  │
│  │ 📜 秘密(变量)   │  │
│  └──────────────────┘  │
│  只有你有钥匙!        │
└────────────────────────┘

外部代码:我想偷看你的余额!
闭包:门都没有!🚪🔒

6️⃣ 柯里化(Currying):函数界的串串 🍢

什么是柯里化?

把一个多参数函数,变成一串单参数函数。

就像吃串串:

  • 🍢 普通函数:一口吃掉一串(所有参数一次传入)
  • 🍢 柯里化:一个一个吃(参数一个一个传入)
代码示例:
# 🍕 普通函数:一次性点餐
def make_pizza(base, sauce, topping):
    return f"制作:{base} + {sauce} + {topping} 披萨!🍕"

pizza1 = make_pizza("薄饼", "番茄酱", "芝士")
print(pizza1)  # 制作:薄饼 + 番茄酱 + 芝士 披萨!

# 🍢 柯里化:分步点餐
def make_pizza_curried(base):
    def add_sauce(sauce):
        def add_topping(topping):
            return f"制作:{base} + {sauce} + {topping} 披萨!🍕"
        return add_topping
    return add_sauce

# 用法1:一步步来
step1 = make_pizza_curried("薄饼")      # 选底
step2 = step1("番茄酱")                  # 选酱
step3 = step2("芝士")                    # 选配料
print(step3)  # 制作:薄饼 + 番茄酱 + 芝士 披萨!

# 用法2:链式调用(更优雅)
pizza2 = make_pizza_curried("厚饼")("烧烤酱")("培根")
print(pizza2)  # 制作:厚饼 + 烧烤酱 + 培根 披萨!

# 用法3:预设默认值(最牛逼)
make_thin_crust_pizza = make_pizza_curried("薄饼")  # 默认薄饼
make_tomato_thin_pizza = make_thin_crust_pizza("番茄酱")  # 默认薄饼+番茄酱

# 现在只需要选配料!
pizza3 = make_tomato_thin_pizza("芝士")
pizza4 = make_tomato_thin_pizza("菠萝")  # 夏威夷披萨(异端!)
pizza5 = make_tomato_thin_pizza("海鲜")

print(pizza3)  # 制作:薄饼 + 番茄酱 + 芝士 披萨!
print(pizza4)  # 制作:薄饼 + 番茄酱 + 菠萝 披萨!
print(pizza5)  # 制作:薄饼 + 番茄酱 + 海鲜 披萨!
为什么要柯里化?
  1. 复用性:可以预设参数,创建特定版本的函数
  2. 灵活性:参数可以分批传入
  3. 可读性:链式调用更优雅
生活比喻:🏗️
普通函数 = 盖房子
- 需要:砖、水泥、钢筋、玻璃...
- 一次性全部到位
- 少一样都不行

柯里化 = 搭积木
- 第一步:选底座 🟦
- 第二步:选主体 🟨
- 第三步:选屋顶 🟥
- 可以随时暂停
- 可以重复使用前几步
实用工具:使用装饰器实现柯里化
def curry(func):
    """柯里化装饰器"""
    def curried(*args, **kwargs):
        if len(args) + len(kwargs) >= func.__code__.co_argcount:
            return func(*args, **kwargs)
        return lambda *more_args, **more_kwargs: curried(*(args + more_args), **{**kwargs, **more_kwargs})
    return curried

@curry
def add_three_numbers(a, b, c):
    return a + b + c

# 多种用法!
print(add_three_numbers(1, 2, 3))  # 6
print(add_three_numbers(1)(2)(3))  # 6
print(add_three_numbers(1, 2)(3))  # 6

add_one = add_three_numbers(1)
add_one_and_two = add_one(2)
result = add_one_and_two(3)
print(result)  # 6

🛠️ Python武器库:内置函数式工具

1️⃣ map():变形金刚 🤖

作用

把一个函数应用到列表的每个元素上,返回新列表。

语法
map(function, iterable)
代码示例:
# 🎨 场景:给数字化妆
numbers = [1, 2, 3, 4, 5]

# 方法1:传统方式(累)
squared = []
for num in numbers:
    squared.append(num ** 2)
print(squared)  # [1, 4, 9, 16, 25]

# 方法2:map方式(爽)
squared = list(map(lambda x: x ** 2, numbers))
print(squared)  # [1, 4, 9, 16, 25]

# 🌟 更多例子
names = ['alice', 'bob', 'charlie']
upper_names = list(map(str.upper, names))
print(upper_names)  # ['ALICE', 'BOB', 'CHARLIE']

# 🔥 处理多个列表
list1 = [1, 2, 3]
list2 = [10, 20, 30]
sums = list(map(lambda x, y: x + y, list1, list2))
print(sums)  # [11, 22, 33]
生活比喻:🏭
map = 流水线加工厂
输入:[🥔, 🥔, 🥔, 🥔] (原料土豆)
  ⬇ 
应用:切片机 (lambda x: 薯片)
  ⬇
输出:[🍟, 🍟, 🍟, 🍟] (成品薯片)
图解:
数字列表:[1, 2, 3, 4, 5]
           ⬇  ⬇  ⬇  ⬇  ⬇
map(平方函数):  
           ⬇  ⬇  ⬇  ⬇  ⬇
结果列表:[1, 4, 9, 16, 25]

2️⃣ filter():守门员 🚪

作用

筛选出满足条件的元素。

语法
filter(function, iterable)
代码示例:
# 🎭 场景:夜店门口的保安
people = [
    {'name': '小明', 'age': 16},
    {'name': '小红', 'age': 22},
    {'name': '小刚', 'age': 17},
    {'name': '小美', 'age': 25},
    {'name': '小智', 'age': 19},
]

# 方法1:传统方式
adults = []
for person in people:
    if person['age'] >= 18:
        adults.append(person)

# 方法2:filter方式(优雅)
adults = list(filter(lambda p: p['age'] >= 18, people))
print(adults)
# [{'name': '小红', 'age': 22}, 
#  {'name': '小美', 'age': 25}, 
#  {'name': '小智', 'age': 19}]

# 🔢 更简单的例子
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# 筛选偶数
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens)  # [2, 4, 6, 8, 10]

# 筛选大于5的数
large_nums = list(filter(lambda x: x > 5, numbers))
print(large_nums)  # [6, 7, 8, 9, 10]
生活比喻:🕵️
filter = 机场安检
所有乘客:👨👩👴👵🧒
    ⬇ 检查护照 + 检查行李
    ⬇
合格乘客:👨👩👴 (小孩没护照,被拦了)
图解:
原始数据:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]filter(是偶数?):
  12345678910 ✅
           ⬇
筛选结果:[2, 4, 6, 8, 10]

3️⃣ reduce():打包大师 📦

作用

把列表"打包"成一个值。

语法
from functools import reduce
reduce(function, iterable, initial_value)
代码示例:
from functools import reduce

# 🧮 场景:计算购物车总价
prices = [10, 25, 8, 15, 30]

# 方法1:传统方式
total = 0
for price in prices:
    total += price
print(total)  # 88

# 方法2:reduce方式
total = reduce(lambda acc, price: acc + price, prices, 0)
print(total)  # 88

# 📊 更多例子
numbers = [1, 2, 3, 4, 5]

# 计算乘积
product = reduce(lambda acc, x: acc * x, numbers, 1)
print(product)  # 120 (1*2*3*4*5)

# 找最大值
maximum = reduce(lambda acc, x: acc if acc > x else x, numbers)
print(maximum)  # 5

# 🔤 字符串拼接
words = ['Python', '函数式', '编程', '真', '爽']
sentence = reduce(lambda acc, word: acc + word, words, '')
print(sentence)  # Python函数式编程真爽
生活比喻:🎂
reduce = 做蛋糕
原料:[面粉, 鸡蛋, 牛奶, 糖, 黄油]
  ⬇ 混合
面糊 = 面粉 + 鸡蛋
  ⬇ 继续混合
面糊 = 面糊 + 牛奶
  ⬇ 继续混合
面糊 = 面糊 + 糖
  ⬇ 继续混合
面糊 = 面糊 + 黄油
  ⬇
最终:一个完整的蛋糕面糊 🎂
图解:
数字:[1, 2, 3, 4, 5]
初始值:0
  ⬇
reduce(加法):
0 + 1 = 1
1 + 2 = 3
3 + 3 = 6
6 + 4 = 10
10 + 5 = 15
  ⬇
结果:15

4️⃣ zip():拉链大师 🤐

作用

把多个列表"拉"到一起。

语法
zip(iterable1, iterable2, ...)
代码示例:
# 👫 场景:配对情侣
boys = ['小明', '小刚', '小智']
girls = ['小红', '小美', '小霞']

# 配对!
couples = list(zip(boys, girls))
print(couples)
# [('小明', '小红'), ('小刚', '小美'), ('小智', '小霞')]

# 💑 更优雅的输出
for boy, girl in zip(boys, girls):
    print(f"{boy} ❤️ {girl}")
# 小明 ❤️ 小红
# 小刚 ❤️ 小美
# 小智 ❤️ 小霞

# 📊 实用例子:合并数据
names = ['Alice', 'Bob', 'Charlie']
ages = [25, 30, 35]
cities = ['北京', '上海', '深圳']

people = list(zip(names, ages, cities))
for name, age, city in people:
    print(f"{name}, {age}岁, 住在{city}")
# Alice, 25岁, 住在北京
# Bob, 30岁, 住在上海
# Charlie, 35岁, 住在深圳

# 🔄 解压(反向操作)
numbers = [(1, 4), (2, 5), (3, 6)]
list1, list2 = zip(*numbers)
print(list1)  # (1, 2, 3)
print(list2)  # (4, 5, 6)
生活比喻:👟
zip = 拉链
左边:[🔴, 🟡, 🟢]
右边:[🔵, 🟣, 🟤]
  ⬇ 拉上拉链
结果:[(🔴,🔵), (🟡,🟣), (🟢,🟤)]

5️⃣ sorted():排序大师 📊

作用

排序,但支持自定义规则!

语法
sorted(iterable, key=function, reverse=False)
代码示例:
# 🏆 场景:运动会排名
students = [
    {'name': '小明', 'score': 85},
    {'name': '小红', 'score': 95},
    {'name': '小刚', 'score': 78},
    {'name': '小美', 'score': 92},
]

# 按分数排序(从高到低)
ranked = sorted(students, key=lambda s: s['score'], reverse=True)
for i, student in enumerate(ranked, 1):
    print(f"🏅 第{i}名: {student['name']}, {student['score']}分")
# 🏅 第1名: 小红, 95分
# 🏅 第2名: 小美, 92分
# 🏅 第3名: 小明, 85分
# 🏅 第4名: 小刚, 78分

# 🔤 按字符串长度排序
words = ['apple', 'zoo', 'banana', 'car', 'elephant']
sorted_words = sorted(words, key=len)
print(sorted_words)
# ['zoo', 'car', 'apple', 'banana', 'elephant']

# 🎯 多条件排序
people = [
    {'name': 'Alice', 'age': 25, 'salary': 5000},
    {'name': 'Bob', 'age': 25, 'salary': 6000},
    {'name': 'Charlie', 'age': 30, 'salary': 5000},
]

# 先按年龄,再按工资排序
sorted_people = sorted(people, key=lambda p: (p['age'], p['salary']))
for p in sorted_people:
    print(f"{p['name']}: {p['age']}岁, ${p['salary']}")
# Alice: 25岁, $5000
# Bob: 25岁, $6000
# Charlie: 30岁, $5000
生活比喻:📚
sorted = 图书馆整理书籍
原始:[C书, A书, B书, D书]
  ⬇ 按字母排序
结果:[A书, B书, C书, D书]

原始:[薄书, 厚书, 中书]
  ⬇ 按厚度排序
结果:[薄书, 中书, 厚书]

🎮 实战演练:从生活到代码

案例1:外卖订单处理系统 🍱

需求:
  1. 筛选出金额大于50元的订单
  2. 给这些订单打9折
  3. 计算总收入
# 订单数据
orders = [
    {'id': 1, 'amount': 45, 'user': '小明'},
    {'id': 2, 'amount': 80, 'user': '小红'},
    {'id': 3, 'amount': 65, 'user': '小刚'},
    {'id': 4, 'amount': 30, 'user': '小美'},
    {'id': 5, 'amount': 120, 'user': '小智'},
]

# 🔥 函数式编程一气呵成!
from functools import reduce

# 步骤1:筛选金额 > 50 的订单
large_orders = filter(lambda o: o['amount'] > 50, orders)

# 步骤2:打9折
discounted_orders = map(lambda o: {**o, 'amount': o['amount'] * 0.9}, large_orders)

# 步骤3:计算总收入
total_income = reduce(lambda acc, o: acc + o['amount'], discounted_orders, 0)

print(f"💰 总收入:{total_income:.2f}元")
# 💰 总收入:238.50元

# 🎯 一行版本(装逼专用)
total = reduce(
    lambda acc, o: acc + o['amount'] * 0.9,
    filter(lambda o: o['amount'] > 50, orders),
    0
)
print(f"💰 总收入:{total:.2f}元")
# 💰 总收入:238.50元
对比传统方式:
# 😓 传统方式(累)
total = 0
for order in orders:
    if order['amount'] > 50:
        discounted = order['amount'] * 0.9
        total += discounted
print(f"💰 总收入:{total:.2f}元")

案例2:学生成绩分析系统 📖

需求:
  1. 找出成绩 >= 90 的优秀学生
  2. 计算优秀学生的平均分
  3. 按分数排序
students = [
    {'name': '小明', 'scores': [85, 92, 88]},
    {'name': '小红', 'scores': [95, 98, 92]},
    {'name': '小刚', 'scores': [78, 82, 75]},
    {'name': '小美', 'scores': [88, 85, 90]},
    {'name': '小智', 'scores': [92, 95, 89]},
]

# 步骤1:计算每个学生的平均分
students_with_avg = list(map(
    lambda s: {
        'name': s['name'],
        'scores': s['scores'],
        'average': sum(s['scores']) / len(s['scores'])
    },
    students
))

# 步骤2:筛选平均分 >= 90 的学生
excellent_students = list(filter(
    lambda s: s['average'] >= 90,
    students_with_avg
))

# 步骤3:按分数排序
sorted_students = sorted(
    excellent_students,
    key=lambda s: s['average'],
    reverse=True
)

# 步骤4:计算优秀学生的平均分
if sorted_students:
    overall_avg = reduce(
        lambda acc, s: acc + s['average'],
        sorted_students,
        0
    ) / len(sorted_students)
    
    print("🏆 优秀学生榜单:")
    for i, student in enumerate(sorted_students, 1):
        print(f"  {i}. {student['name']}: {student['average']:.2f}分")
    print(f"\n📊 优秀学生平均分:{overall_avg:.2f}分")

# 输出:
# 🏆 优秀学生榜单:
#   1. 小红: 95.00分
#   2. 小智: 92.00分
# 
# 📊 优秀学生平均分:93.50分

案例3:电商购物车系统 🛒

# 商品数据
products = [
    {'id': 1, 'name': 'iPhone 15', 'price': 5999, 'category': '电子'},
    {'id': 2, 'name': 'AirPods', 'price': 1299, 'category': '电子'},
    {'id': 3, 'name': 'T恤', 'price': 99, 'category': '服装'},
    {'id': 4, 'name': 'MacBook', 'price': 9999, 'category': '电子'},
    {'id': 5, 'name': '牛仔裤', 'price': 299, 'category': '服装'},
]

# 购物车
cart = [
    {'product_id': 1, 'quantity': 1},
    {'product_id': 2, 'quantity': 2},
    {'product_id': 3, 'quantity': 3},
]

# 🎯 需求:计算购物车总价(电子产品打9折)

# 步骤1:给购物车商品添加详细信息
cart_with_details = list(map(
    lambda item: {
        **item,
        'product': next(p for p in products if p['id'] == item['product_id'])
    },
    cart
))

# 步骤2:计算每个商品的小计(含折扣)
cart_with_subtotal = list(map(
    lambda item: {
        **item,
        'subtotal': (
            item['product']['price'] * item['quantity'] * 0.9
            if item['product']['category'] == '电子'
            else item['product']['price'] * item['quantity']
        )
    },
    cart_with_details
))

# 步骤3:计算总价
total = reduce(
    lambda acc, item: acc + item['subtotal'],
    cart_with_subtotal,
    0
)

# 打印购物车详情
print("🛒 购物车:")
print("-" * 60)
for item in cart_with_subtotal:
    product = item['product']
    discount = " (9折)" if product['category'] == '电子' else ""
    print(f"{product['name']:15} x{item['quantity']}{discount:10} = ¥{item['subtotal']:.2f}")
print("-" * 60)
print(f"{'总计':27} = ¥{total:.2f}")

# 输出:
# 🛒 购物车:
# ------------------------------------------------------------
# iPhone 15       x1 (9折)      = ¥5399.10
# AirPods         x2 (9折)      = ¥2338.20
# T恤             x3            = ¥297.00
# ------------------------------------------------------------
# 总计                          = ¥8034.30

案例4:文本分析工具 📝

# 📄 场景:分析一篇文章
text = """
Python是一种广泛使用的高级编程语言。
Python具有简洁清晰的语法,强大的功能。
Python支持多种编程范式,包括面向对象和函数式编程。
学习Python是一个明智的选择!
"""

# 需求:
# 1. 统计每个单词出现的次数
# 2. 找出出现次数最多的前3个单词

from functools import reduce
import re

# 步骤1:分词(简单版,按空格和标点分割)
words = re.findall(r'\b\w+\b', text.lower())
print(f"📊 总词数:{len(words)}")

# 步骤2:统计词频
word_count = reduce(
    lambda acc, word: {**acc, word: acc.get(word, 0) + 1},
    words,
    {}
)

# 步骤3:排序
sorted_words = sorted(
    word_count.items(),
    key=lambda item: item[1],
    reverse=True
)

# 步骤4:取前3个
top_3 = list(map(
    lambda item: f"{item[0]}: {item[1]}次",
    sorted_words[:3]
))

print("\n🏆 Top 3 高频词:")
for i, word_info in enumerate(top_3, 1):
    print(f"  {i}. {word_info}")

# 输出:
# 📊 总词数:27
# 
# 🏆 Top 3 高频词:
#   1. python: 4次
#   2. 编程: 2次
#   3. 是: 2次

🚀 进阶技巧:装逼必备

1️⃣ 列表推导式(List Comprehension):函数式编程的好兄弟 🤝

虽然不是纯函数式,但非常好用!

# 传统方式
squares = []
for i in range(10):
    squares.append(i ** 2)

# map方式
squares = list(map(lambda x: x ** 2, range(10)))

# 列表推导式(最优雅!)
squares = [x ** 2 for x in range(10)]

# 带条件的列表推导式
even_squares = [x ** 2 for x in range(10) if x % 2 == 0]
print(even_squares)  # [0, 4, 16, 36, 64]

# 嵌套列表推导式
matrix = [[i * j for j in range(1, 4)] for i in range(1, 4)]
print(matrix)
# [[1, 2, 3],
#  [2, 4, 6],
#  [3, 6, 9]]

2️⃣ 链式调用:像写诗一样写代码 ✍️

# 💎 优雅的链式调用
from functools import reduce

result = (
    reduce(
        lambda acc, x: acc + x,
        map(
            lambda x: x ** 2,
            filter(
                lambda x: x % 2 == 0,
                range(10)
            )
        ),
        0
    )
)
print(result)  # 120 (0² + 2² + 4² + 6² + 8²)

# 🎯 可读性更好的版本
numbers = range(10)
evens = filter(lambda x: x % 2 == 0, numbers)
squared = map(lambda x: x ** 2, evens)
total = reduce(lambda acc, x: acc + x, squared, 0)
print(total)  # 120

3️⃣ 自定义函数式工具 🔧

# 🛠️ 工具1:compose(函数组合)
def compose(*functions):
    """从右到左组合函数"""
    return reduce(
        lambda f, g: lambda x: f(g(x)),
        functions,
        lambda x: x
    )

# 使用示例
add_10 = lambda x: x + 10
multiply_2 = lambda x: x * 2
square = lambda x: x ** 2

# 组合:先加10,再乘2,最后平方
combined = compose(square, multiply_2, add_10)
result = combined(5)  # ((5 + 10) * 2) ** 2 = 900
print(result)  # 900

# 🛠️ 工具2:pipe(管道,从左到右)
def pipe(*functions):
    """从左到右组合函数"""
    return reduce(
        lambda f, g: lambda x: g(f(x)),
        functions,
        lambda x: x
    )

# 使用示例
piped = pipe(add_10, multiply_2, square)
result = piped(5)  # 同上
print(result)  # 900

# 🛠️ 工具3:partial(部分应用)
from functools import partial

def power(base, exponent):
    return base ** exponent

# 创建平方函数
square = partial(power, exponent=2)
print(square(5))  # 25

# 创建立方函数
cube = partial(power, exponent=3)
print(cube(5))  # 125

4️⃣ 惰性求值(Lazy Evaluation):懒得像猫 🐱

# 🐌 传统方式:立即计算所有结果(内存杀手)
numbers = [x ** 2 for x in range(1000000)]  # 占用大量内存!

# 😺 生成器:只在需要时计算(内存友好)
numbers = (x ** 2 for x in range(1000000))  # 几乎不占内存!

# 例子:找出前5个能被7整除的平方数
squares = (x ** 2 for x in range(1000000))
divisible_by_7 = filter(lambda x: x % 7 == 0, squares)

# 只取前5个(其他的都不会计算)
first_5 = list(map(str, list(divisible_by_7)[:5]))
print(', '.join(first_5))  # 0, 49, 196, 441, 784

# 🎯 自定义生成器
def fibonacci():
    """无限斐波那契数列生成器"""
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

# 只取前10个
fib = fibonacci()
first_10 = [next(fib) for _ in range(10)]
print(first_10)  # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

🎓 总结:函数式编程的正确打开方式

✅ 什么时候用函数式编程?

场景适合度理由
数据转换⭐⭐⭐⭐⭐map/filter/reduce 天生适合
数据分析⭐⭐⭐⭐⭐链式调用,逻辑清晰
并行计算⭐⭐⭐⭐⭐纯函数无副作用,线程安全
数学计算⭐⭐⭐⭐函数思维贴近数学
UI交互⭐⭐⭐看情况,React就是函数式
游戏开发⭐⭐性能要求高,命令式更好
系统编程需要大量状态管理

❌ 什么时候不要用?

# 🚫 别这样:强行函数式
# 这样写同事会打你的
result = reduce(
    lambda acc, x: (
        acc + [x ** 2] if x % 2 == 0 else acc
    ),
    filter(
        lambda x: x > 0,
        map(
            lambda x: x - 1,
            [1, 2, 3, 4, 5]
        )
    ),
    []
)

# ✅ 这样写:可读性第一
numbers = [x - 1 for x in [1, 2, 3, 4, 5] if x - 1 > 0]
result = [x ** 2 for x in numbers if x % 2 == 0]

🎯 函数式编程黄金法则

  1. 可读性 > 简洁性 📖
    • 别为了一行代码而牺牲可读性
  2. 实用 > 教条 🛠️
    • Python 不是 Haskell,该用循环就用循环
  3. 测试 > 理论 🧪
    • 纯函数超级好测试,充分利用这一点
  4. 渐进 > 激进 🐢
    • 慢慢引入函数式概念,别一次性重构所有代码

🎁 最后的彩蛋:函数式编程速查表

# 📋 速查表
from functools import reduce, partial

# 1. 转换数据
list(map(func, data))                    # 转换
[func(x) for x in data]                  # 列表推导式

# 2. 筛选数据
list(filter(condition, data))            # 筛选
[x for x in data if condition(x)]        # 列表推导式

# 3. 聚合数据
reduce(func, data, initial)              # 聚合
sum(data)                                # 求和
max(data)                                # 最大值
min(data)                                # 最小值

# 4. 排序数据
sorted(data, key=func, reverse=True)     # 排序

# 5. 组合数据
list(zip(list1, list2))                  # 拉链

# 6. 部分应用
new_func = partial(func, arg1=value)     # 柯里化

# 7. 函数组合
compose(f, g, h)(x) == f(g(h(x)))        # 从右到左
pipe(f, g, h)(x) == h(g(f(x)))           # 从左到右

# 8. 惰性求值
(x for x in data)                        # 生成器表达式

🎉 结语

恭喜你!🎊 你已经掌握了 Python 函数式编程的核心知识!

现在你可以:

  • ✅ 写出更简洁、优雅的代码
  • ✅ 提高代码的可读性和可维护性
  • ✅ 在面试时优雅地装逼
  • ✅ 让同事对你刮目相看

记住:

函数式编程不是银弹,但它是你武器库里的利器!🗡️

下一步该做什么?

  1. 实践 💪
    • 把今天学的知识用到实际项目中
  2. 阅读 📚
    • 看看 itertools 模块,里面有更多函数式工具
  3. 分享 🎤
    • 教会别人是最好的学习方式
  4. 思考 🤔
    • 什么时候该用函数式?什么时候不该用?

📚 参考资料


💬 最后的最后

如果你觉得这份文档对你有帮助,请:

  • ⭐ 收藏它
  • 📤 分享给朋友
  • 💬 留下你的反馈

Happy Coding! 🚀

print("愿函数与你同在!May the Function be with you! 🎩✨")

转存失败,建议直接上传图片文件
感谢阅读!现在去写些美丽的代码吧!