想象一下,如果编程就像搭积木一样,通过组合简单的模块来构建复杂的功能,而不是编写冗长的指令序列。这正是函数式编程的魅力所在!它不仅仅是一种技术,更是一种思维方式,让代码变得更简洁、更可预测、更易于理解。
函数式编程的核心理念
- 不变性:数据的安全保障
- 纯函数:相同的输入,永远得到相同的输出
- 函数是最重要的
实战代码:函数式编程的实践
基础函数式操作
python
# 传统方式 vs 函数式方式
# 传统命令式编程
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# 筛选偶数并计算平方
result_imperative = []
for num in numbers:
if num % 2 == 0:
result_imperative.append(num ** 2)
print(f"命令式结果: {result_imperative}")
# 函数式编程方式
result_functional = list(map(lambda x: x ** 2,
filter(lambda x: x % 2 == 0, numbers)))
print(f"函数式结果: {result_functional}")
# 更清晰的写法(使用生成器表达式)
result_clear = [x ** 2 for x in numbers if x % 2 == 0]
print(f"清晰写法: {result_clear}")
高阶函数应用
python
from functools import reduce
from typing import List, Callable
def compose(*functions: Callable) -> Callable:
"""函数组合:将多个函数组合成一个新函数"""
def composed(arg):
result = arg
for func in reversed(functions):
result = func(result)
return result
return composed
def pipe(*functions: Callable) -> Callable:
"""管道操作:从左到右执行函数序列"""
def piped(arg):
result = arg
for func in functions:
result = func(result)
return result
return piped
# 创建一些小的纯函数
def add(x: int) -> Callable[[int], int]:
"""柯里化的加法函数"""
return lambda y: x + y
def multiply(x: int) -> Callable[[int], int]:
"""柯里化的乘法函数"""
return lambda y: x * y
def filter_even(numbers: List[int]) -> List[int]:
"""筛选偶数"""
return list(filter(lambda x: x % 2 == 0, numbers))
def square_all(numbers: List[int]) -> List[int]:
"""对所有数字求平方"""
return list(map(lambda x: x ** 2, numbers))
def sum_all(numbers: List[int]) -> int:
"""求和"""
return reduce(lambda x, y: x + y, numbers, 0)
# 使用函数组合构建复杂操作
process_numbers = pipe(
filter_even, # 第一步:筛选偶数
square_all, # 第二步:求平方
sum_all # 第三步:求和
)
# 测试函数组合
numbers = [1, 2, 3, 4, 5, 6]
result = process_numbers(numbers)
print(f"处理结果: {result}") # 4 + 16 + 36 = 56
# 柯里化函数的使用
add_five = add(5)
multiply_by_three = multiply(3)
print(f"5 + 10 = {add_five(10)}")
print(f"3 × 7 = {multiply_by_three(7)}")
# 组合柯里化函数
add_then_multiply = compose(multiply_by_three, add_five)
print(f"(5 + 10) × 3 = {add_then_multiply(10)}")
不可变数据结构
python
from typing import Dict, List, Any
from copy import deepcopy
def update_in(data: Dict, keys: List, value: Any) -> Dict:
"""不可变地更新嵌套字典的特定路径"""
if len(keys) == 0:
return value
key = keys[0]
remaining_keys = keys[1:]
# 创建数据的深拷贝
new_data = deepcopy(data)
if isinstance(new_data, dict):
if key in new_data:
new_data[key] = update_in(new_data[key], remaining_keys, value)
else:
new_data[key] = update_in({}, remaining_keys, value)
else:
# 如果不是字典,创建新的字典结构
new_data = {key: update_in({}, remaining_keys, value)}
return new_data
def assoc(data: Dict, key: str, value: Any) -> Dict:
"""不可变地设置字典键值"""
new_data = data.copy()
new_data[key] = value
return new_data
def dissoc(data: Dict, key: str) -> Dict:
"""不可变地删除字典键"""
new_data = data.copy()
if key in new_data:
del new_data[key]
return new_data
# 使用不可变数据操作
user_data = {
"name": "张三",
"age": 25,
"address": {
"city": "北京",
"street": "朝阳路"
},
"hobbies": ["阅读", "编程"]
}
print("原始数据:", user_data)
# 不可变更新
new_user = assoc(user_data, "age", 26)
print("更新年龄后:", new_user)
print("原始数据未改变:", user_data["age"])
# 删除属性
user_without_age = dissoc(user_data, "age")
print("删除年龄后:", user_without_age)
# 深层更新
updated_user = update_in(user_data, ["address", "city"], "上海")
print("更新城市后:", updated_user)
print("原始地址未改变:", user_data["address"]["city"])
函数式数据处理
python
from functools import partial
from operator import itemgetter, attrgetter
class Product:
def __init__(self, name: str, price: float, category: str):
self.name = name
self.price = price
self.category = category
def __repr__(self):
return f"Product({self.name}, ${self.price}, {self.category})"
# 创建产品列表
products = [
Product("笔记本电脑", 5999, "电子产品"),
Product("智能手机", 3999, "电子产品"),
Product("书籍", 49, "文教用品"),
Product("咖啡", 35, "食品饮料"),
Product("鼠标", 89, "电子产品"),
Product("笔记本", 15, "文教用品")
]
# 函数式数据处理管道
def create_data_pipeline(*transformations):
"""创建数据处理管道"""
def pipeline(data):
return reduce(lambda d, transform: transform(d),
transformations, data)
return pipeline
# 各种数据处理函数
def filter_by_category(category: str):
"""按类别筛选的柯里化函数"""
return partial(filter, lambda p: p.category == category)
def filter_by_price(max_price: float):
"""按价格筛选的柯里化函数"""
return partial(filter, lambda p: p.price <= max_price)
def sort_by_price(descending: bool = False):
"""按价格排序的柯里化函数"""
return partial(sorted, key=attrgetter('price'), reverse=descending)
def get_names():
"""提取产品名称"""
return partial(map, attrgetter('name'))
def calculate_total_price():
"""计算总价格"""
return partial(reduce, lambda total, p: total + p.price)
# 构建复杂的数据处理管道
affordable_electronics = create_data_pipeline(
filter_by_category("电子产品"),
filter_by_price(5000),
sort_by_price(descending=True)
)
cheap_product_names = create_data_pipeline(
filter_by_price(100),
get_names(),
list
)
total_electronics_price = create_data_pipeline(
filter_by_category("电子产品"),
calculate_total_price()
)
# 使用数据处理管道
print("实惠的电子产品:")
for product in affordable_electronics(products):
print(f" {product}")
print(f"\n便宜商品名称: {list(cheap_product_names(products))}")
# 注意:calculate_total_price 返回的是reduce函数,需要传入初始值0
electronics_price = total_electronics_price(products)(0)
print(f"电子产品总价: ${electronics_price}")
递归和惰性求值
python
from itertools import islice
def fibonacci():
"""生成无限斐波那契数列(惰性求值)"""
a, b = 0, 1
while True:
yield a
a, b = b, a + b
def recursive_sum(numbers: List[int]) -> int:
"""递归方式求和"""
if not numbers:
return 0
return numbers[0] + recursive_sum(numbers[1:])
def recursive_max(numbers: List[int]) -> int:
"""递归方式求最大值"""
if len(numbers) == 1:
return numbers[0]
rest_max = recursive_max(numbers[1:])
return numbers[0] if numbers[0] > rest_max else rest_max
def trampoline(func):
"""蹦床函数:优化递归,防止栈溢出"""
def trampolined(*args, **kwargs):
result = func(*args, **kwargs)
while callable(result):
result = result()
return result
return trampolined
# 使用惰性序列
print("斐波那契数列前10项:")
fib_sequence = islice(fibonacci(), 10)
print(list(fib_sequence))
# 使用递归函数
numbers = [1, 5, 3, 9, 2]
print(f"递归求和: {recursive_sum(numbers)}")
print(f"递归求最大值: {recursive_max(numbers)}")
# 记忆化装饰器(缓存函数结果)
def memoize(func):
"""记忆化装饰器:缓存函数计算结果"""
cache = {}
def memoized(*args):
if args in cache:
return cache[args]
result = func(*args)
cache[args] = result
return result
return memoized
@memoize
def factorial(n: int) -> int:
"""记忆化的阶乘函数"""
if n <= 1:
return 1
return n * factorial(n - 1)
print(f"\n记忆化阶乘:")
print(f"5! = {factorial(5)}")
print(f"10! = {factorial(10)}")
# 第二次调用会使用缓存
print(f"5! (缓存) = {factorial(5)}")
函数式编程原则
- 纯函数优先
- 不可变性原则
- 声明式编程
- 组合优于继承