← 返回首页
🐍

functools模块

📂 python ⏱ 4 min 686 words

functools模块概述

functools模块提供了用于处理函数的高阶操作,是函数式编程的重要工具。

lru_cache - 缓存装饰器

lru_cache是一个装饰器,用于缓存函数的返回结果,提高性能。

from functools import lru_cache

# 基本用法
@lru_cache(maxsize=128)
def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

# 使用
print(fibonacci(50))  # 输出: 12586269025
print(fibonacci.cache_info())  # 查看缓存信息

# 清除缓存
fibonacci.cache_clear()

缓存信息

@lru_cache(maxsize=10)
def expensive_function(x):
    print(f"计算 {x}...")
    return x * x

# 第一次调用
expensive_function(5)
# 输出: 计算 5...

# 第二次调用(使用缓存)
expensive_function(5)
# 不输出任何内容

# 查看缓存信息
print(expensive_function.cache_info())
# 输出: CacheInfo(hits=1, misses=1, maxsize=10, currsize=1)

partial - 偏函数

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

# 实际应用:排序
from operator import itemgetter

students = [
    {'name': 'Alice', 'age': 25, 'score': 90},
    {'name': 'Bob', 'age': 22, 'score': 85},
    {'name': 'Charlie', 'age': 23, 'score': 92}
]

# 按年龄排序
sort_by_age = partial(sorted, key=itemgetter('age'))
sorted_students = sort_by_age(students)
print([s['name'] for s in sorted_students])
# 输出: ['Bob', 'Charlie', 'Alice']

reduce - 归约函数

reduce将一个函数应用于序列的所有元素,累积结果。

from functools import reduce

# 基本用法
numbers = [1, 2, 3, 4, 5]

# 求和
total = reduce(lambda a, b: a + b, numbers)
print(total)  # 输出: 15

# 求积
product = reduce(lambda a, b: a * b, numbers)
print(product)  # 输出: 120

# 实际应用:扁平化嵌套列表
nested = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened = reduce(lambda a, b: a + b, nested)
print(flattened)  # 输出: [1, 2, 3, 4, 5, 6, 7, 8, 9]

# 实际应用:合并字典
dict1 = {'a': 1, 'b': 2}
dict2 = {'c': 3, 'd': 4}
dict3 = {'e': 5, 'f': 6}

merged = reduce(lambda a, b: {**a, **b}, [dict1, dict2, dict3])
print(merged)
# 输出: {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6}

wraps - 函数包装

wraps用于保留被装饰函数的元信息。

from functools import wraps

def my_decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        """包装器文档字符串"""
        print("装饰器执行前")
        result = func(*args, **kwargs)
        print("装饰器执行后")
        return result
    return wrapper

@my_decorator
def say_hello(name):
    """向某人打招呼"""
    print(f"Hello, {name}!")

# 使用
say_hello("Alice")

# 查看函数信息
print(say_hello.__name__)  # 输出: say_hello
print(say_hello.__doc__)   # 输出: 向某人打招呼

# 没有@wraps时,__name__会是'wrapper'

其他实用函数

total_ordering - 自动比较方法

from functools import total_ordering

@total_ordering
class Student:
    def __init__(self, name, score):
        self.name = name
        self.score = score
    
    def __eq__(self, other):
        return self.score == other.score
    
    def __lt__(self, other):
        return self.score < other.score

# 使用
s1 = Student("Alice", 90)
s2 = Student("Bob", 85)

print(s1 > s2)   # 输出: True
print(s1 >= s2)  # 输出: True
print(s1 <= s2)  # 输出: False

singledispatch - 单分派泛型函数

from functools import singledispatch

@singledispatch
def process(value):
    raise NotImplementedError(f"Unsupported type: {type(value)}")

@process.register(int)
def _(value):
    return f"Processing integer: {value}"

@process.register(str)
def _(value):
    return f"Processing string: {value}"

@process.register(list)
def _(value):
    return f"Processing list with {len(value)} items"

# 使用
print(process(42))        # 输出: Processing integer: 42
print(process("hello"))   # 输出: Processing string: hello
print(process([1, 2, 3])) # 输出: Processing list with 3 items

cached_property - 缓存属性

from functools import cached_property

class DataAnalyzer:
    def __init__(self, data):
        self.data = data
    
    @cached_property
    def mean(self):
        """计算平均值(只计算一次)"""
        print("计算平均值...")
        return sum(self.data) / len(self.data)
    
    @cached_property
    def std_dev(self):
        """计算标准差(只计算一次)"""
        print("计算标准差...")
        mean = self.mean  # 使用缓存的mean
        return (sum((x - mean) ** 2 for x in self.data) / len(self.data)) ** 0.5

# 使用
analyzer = DataAnalyzer([1, 2, 3, 4, 5])
print(analyzer.mean)   # 输出: 计算平均值... 3.0
print(analyzer.mean)   # 输出: 3.0(不重新计算)
print(analyzer.std_dev) # 输出: 计算标准差... 1.414...

实际应用案例

1. 函数缓存

from functools import lru_cache
import time

@lru_cache(maxsize=None)
def fibonacci_optimized(n):
    """优化的斐波那契数列"""
    if n < 2:
        return n
    return fibonacci_optimized(n-1) + fibonacci_optimized(n-2)

# 测试性能
start = time.time()
result = fibonacci_optimized(100)
elapsed = time.time() - start
print(f"结果: {result}")
print(f"耗时: {elapsed:.6f}秒")

2. 函数组合

from functools import reduce

def compose(*functions):
    """函数组合"""
    return reduce(lambda f, g: lambda x: f(g(x)), functions)

# 使用
def add_one(x):
    return x + 1

def multiply_by_two(x):
    return x * 2

def square(x):
    return x ** 2

# 创建组合函数
transform = compose(square, multiply_by_two, add_one)
print(transform(3))  # 输出: 64 ((3+1)*2)^2

3. 配置工厂

from functools import partial

def create_validator(min_length=None, max_length=None, pattern=None):
    """创建验证器"""
    def validate(value):
        if min_length and len(value) < min_length:
            return False
        if max_length and len(value) > max_length:
            return False
        if pattern:
            import re
            if not re.match(pattern, value):
                return False
        return True
    return validate

# 创建不同类型的验证器
username_validator = create_validator(min_length=3, max_length=20)
password_validator = create_validator(min_length=8, pattern=r'^[a-zA-Z0-9]+$')

print(username_validator("ab"))      # 输出: False
print(username_validator("alice"))   # 输出: True
print(password_validator("pass123")) # 输出: False
print(password_validator("pass1234")) # 输出: True

性能优化

import time
from functools import lru_cache

# 不使用缓存
def fibonacci_no_cache(n):
    if n < 2:
        return n
    return fibonacci_no_cache(n-1) + fibonacci_no_cache(n-2)

# 使用缓存
@lru_cache(maxsize=None)
def fibonacci_with_cache(n):
    if n < 2:
        return n
    return fibonacci_with_cache(n-1) + fibonacci_with_cache(n-2)

# 测试性能
n = 30

start = time.time()
result1 = fibonacci_no_cache(n)
time1 = time.time() - start

start = time.time()
result2 = fibonacci_with_cache(n)
time2 = time.time() - start

print(f"无缓存: {time1:.4f}秒")
print(f"有缓存: {time2:.6f}秒")
print(f"加速比: {time1/time2:.0f}倍")

最佳实践

functools模块是Python函数式编程的重要工具,掌握它们能让你的代码更加高效和优雅。