副标题:老板再也不用担心我的代码写成一坨💩了!
📖 目录
🎯 开篇:函数式编程是啥玩意儿?
先说个故事 📚
想象你是一家奶茶店的老板(恭喜发财!💰),每天要处理很多订单:
顾客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
- ❌ 偷偷把你的钱包藏起来
- ❌ 给你的答案同时改变世界
这就是纯函数!
特点:
- 相同输入 ➜ 相同输出(可预测)
- 没有副作用(不搞事情)
代码示例:
# ✅ 纯函数:好朋友
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 处理 5 和 3
✅ 结果:8
📢 老板说:用 multiply 处理 5 和 3
✅ 结果: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) # 制作:薄饼 + 番茄酱 + 海鲜 披萨!
为什么要柯里化?
- 复用性:可以预设参数,创建特定版本的函数
- 灵活性:参数可以分批传入
- 可读性:链式调用更优雅
生活比喻:🏗️
普通函数 = 盖房子
- 需要:砖、水泥、钢筋、玻璃...
- 一次性全部到位
- 少一样都不行
柯里化 = 搭积木
- 第一步:选底座 🟦
- 第二步:选主体 🟨
- 第三步:选屋顶 🟥
- 可以随时暂停
- 可以重复使用前几步
实用工具:使用装饰器实现柯里化
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(是偶数?):
1 ❌ 2 ✅ 3 ❌ 4 ✅ 5 ❌ 6 ✅ 7 ❌ 8 ✅ 9 ❌ 10 ✅
⬇
筛选结果:[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:外卖订单处理系统 🍱
需求:
- 筛选出金额大于50元的订单
- 给这些订单打9折
- 计算总收入
# 订单数据
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:学生成绩分析系统 📖
需求:
- 找出成绩 >= 90 的优秀学生
- 计算优秀学生的平均分
- 按分数排序
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]
🎯 函数式编程黄金法则
- 可读性 > 简洁性 📖
- 别为了一行代码而牺牲可读性
- 实用 > 教条 🛠️
- Python 不是 Haskell,该用循环就用循环
- 测试 > 理论 🧪
- 纯函数超级好测试,充分利用这一点
- 渐进 > 激进 🐢
- 慢慢引入函数式概念,别一次性重构所有代码
🎁 最后的彩蛋:函数式编程速查表
# 📋 速查表
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 函数式编程的核心知识!
现在你可以:
- ✅ 写出更简洁、优雅的代码
- ✅ 提高代码的可读性和可维护性
- ✅ 在面试时优雅地装逼
- ✅ 让同事对你刮目相看
记住:
函数式编程不是银弹,但它是你武器库里的利器!🗡️
下一步该做什么?
- 实践 💪
- 把今天学的知识用到实际项目中
- 阅读 📚
- 看看
itertools模块,里面有更多函数式工具
- 看看
- 分享 🎤
- 教会别人是最好的学习方式
- 思考 🤔
- 什么时候该用函数式?什么时候不该用?
📚 参考资料
💬 最后的最后
如果你觉得这份文档对你有帮助,请:
- ⭐ 收藏它
- 📤 分享给朋友
- 💬 留下你的反馈
Happy Coding! 🚀
print("愿函数与你同在!May the Function be with you! 🎩✨")
感谢阅读!现在去写些美丽的代码吧!