Python functools 模块全方法详解

内容分享10小时前发布
0 1 0

functools 是python标准库中用于高阶函数操作的核心模块,提供函数式编程工具(如装饰器、部分函数应用、缓存等)本文将探索 functools 模块所有公开方法的功能、使用场景、代码示例、输出结果!


方法

核心用途

版本要求

典型场景

reduce

累积计算

所有版本

求和/乘积

partial/partialmethod

参数固定

所有版本

柯里化、简化调用

wraps/update_wrapper

装饰器元数据维护

所有版本

自定义装饰器

lru_cache/cache

结果缓存

cache: 3.9+

递归优化、I/O 缓存

cached_property

属性缓存

3.8+

开销大的属性计算

total_ordering

比较方法生成

所有版本

自定义类比较

singledispatch/method

类型分派

method: 3.8+

多类型统一处理

cmp_to_key

比较函数转换

所有版本

兼容旧版排序逻辑


1.functools.reduce(function, iterable[, initializer])

功能:将二元函数 function 累积应用于 iterable 的元素,从左到右,将序列缩减为单个值。

参数:

  • function:接受两个参数的函数(如 lambda x, y: x + y)
  • iterable:可迭代对象(如列表)
  • initializer(可选):初始值,若提供则作为第一次调用的左参数

使用场景:替代循环实现累积计算(如求和、阶乘)。

from functools import reduce

# 示例1:计算列表元素和
result = reduce(lambda x, y: x + y, [1, 2, 3, 4, 5])
print(result)  # 输出: 15 (计算过程: (((1+2)+3)+4)+5)

# 示例2:带初始值的乘积
result = reduce(lambda x, y: x * y, [1, 2, 3], 10)
print(result)  # 输出: 60 (计算过程: (10*1)*2*3)

2.functools.partial(func, *args, **keywords)

功能:固定函数 func 的部分参数,返回一个新 **可调用对象**(偏函数)。

参数:

  • func:原始函数
  • *args:位置参数固定值
  • **keywords:关键字参数固定值

使用场景:简化函数调用(如固定配置参数)、柯里化。

from functools import partial

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

# 固定 base=2,创建计算平方的新函数
square = partial(power, exponent=2)
print(square(4))  # 输出: 16

# 固定 exponent=3,创建计算立方的新函数
cube = partial(power, exponent=3)
print(cube(3))  # 输出: 27

3.functools.partialmethod(func, *args, **keywords)

功能:与 partial 类似,但专为 **类方法** 设计(需在类内部使用)。

参数:同 partial。

使用场景:在类中定义部分参数固定的方法。

from functools import partialmethod

class Cell:
    def set_state(self, state, temporary=False):
        print(f"State set to {state}, temporary={temporary}")
    
    # 创建固定 temporary=True 的方法
    set_temp_state = partialmethod(set_state, temporary=True)

cell = Cell()
cell.set_temp_state("active")  # 输出: State set to active, temporary=True

4.functools.update_wrapper(wrapper, wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES)

功能:将 wrapped 函数的元数据(如 __name__, __doc__)复制到 wrapper 函数。

参数:

  • wrapper:装饰器函数
  • wrapped:被装饰的原始函数
  • assigned:需复制的属性列表(默认复制 __name__, __doc__ 等)
  • updated:需更新的属性列表(默认更新 __dict__)

使用场景:手动编写装饰器时保留原始函数元信息。

from functools import update_wrapper

def my_decorator(func):
    def wrapper(*args, **kwargs):
        """Wrapper docstring"""
        return func(*args, **kwargs)
    update_wrapper(wrapper, func)  # 关键:复制元数据
    return wrapper

@my_decorator
def example():
    """Example docstring"""
    pass

print(example.__name__)  # 输出: example (未复制时会输出 'wrapper')
print(example.__doc__)   # 输出: Example docstring

5.functools.wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES)

功能:update_wrapper 的装饰器版本,用于简化装饰器元数据维护。

参数:同 update_wrapper。

使用场景:所有自定义装饰器的必备工具。

from functools import wraps

def logging_decorator(func):
    @wraps(func)  # 自动处理元数据复制
    def wrapper(*args, **kwargs):
        print(f"Calling {func.__name__}")
        return func(*args, **kwargs)
    return wrapper

@logging_decorator
def greet(name):
    """问候函数"""
    print(f"Hello, {name}!")

greet("Alice")
# 输出:
# Calling greet
# Hello, Alice!
print(greet.__name__)  # 输出: greet
print(greet.__doc__)   # 输出: 问候函数

6.functools.lru_cache(maxsize=128, typed=False)

功能LRU(Least Recently Used)缓存装饰器,缓存函数结果以提升重复调用性能。

参数

  • maxsize:缓存最大条目数(设为 None 表明无限制)
  • typed:若 True,区分不同参数类型(如 3 和 3.0 视为不同键)

使用场景:加速递归计算(如斐波那契数列)、避免重复 I/O 操作。

from functools import lru_cache

@lru_cache(maxsize=32)
def fibonacci(n):
    if n <= 1:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

print(fibonacci(100))  # 输出: 354224848179261915075
print(fibonacci.cache_info())  # 输出缓存统计: CacheInfo(hits=..., misses=..., ...)

7.functools.cached_property(func)

功能:将类方法转换为 缓存属性,首次访问计算值后缓存结果(实例级缓存)。

注意:Python 3.8+ 引入,适用于 实例方法(非类方法)。

使用场景:避免重复计算开销大的属性(如数据库查询结果)。

from functools import cached_property

class Circle:
    def __init__(self, radius):
        self.radius = radius
    
    @cached_property
    def area(self):
        print("计算面积...")
        return 3.14 * self.radius ** 2

c = Circle(5)
print(c.area)  # 输出: 计算面积... 
 78.5
print(c.area)  # 输出: 78.5 (无"计算面积...",说明已缓存)

8.functools.total_ordering(cls)

功能类装饰器,根据用户定义的 部分比较方法 自动生成完整的比较操作符(<, <=, >, >=)。

要求:必须实现 __eq__ 和 **至少一个** 比较方法(如 __lt__)。

使用场景:简化自定义类的比较逻辑。

from functools import total_ordering

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

s1 = Student(85)
s2 = Student(90)
print(s1 < s2)   # 输出: True
print(s1 <= s2)  # 输出: True (由装饰器自动生成)
print(s1 > s2)   # 输出: False

9.functools.singledispatch(default)

功能单分派泛型函数装饰器,根据 第一个参数的类型 动态选择实现(类似函数重载)。

使用场景:处理不同数据类型的统一接口(如序列化函数)。

from functools import singledispatch

@singledispatch
def process(data):
    print(f"默认处理: {data}")

@process.register
def _(data: int):
    print(f"处理整数: {data * 2}")

@process.register(str)
def _(data):
    print(f"处理字符串: {data.upper()}")

process(10)      # 输出: 处理整数: 20
process("hello") # 输出: 处理字符串: HELLO
process([1, 2])  # 输出: 默认处理: [1, 2]

10.functools.singledispatchmethod(func)

功能:singledispatch 的方法版本,用于类中的方法。

注意:Python 3.8+ 引入。

使用场景:在类中实现基于参数类型的方法重载。

from functools import singledispatchmethod

class Processor:
    @singledispatchmethod
    def process(self, data):
        print(f"默认处理: {data}")
    
    @process.register
    def _(self, data: int):
        print(f"处理整数: {data * 2}")
    
    @process.register
    def _(self, data: str):
        print(f"处理字符串: {data.upper()}")

p = Processor()
p.process(42)      # 输出: 处理整数: 84
p.process("test")  # 输出: 处理字符串: TEST

11.functools.cmp_to_key(func)

功能:将 Python 2 风格的 比较函数(cmp(a, b) 返回 -1/0/1)转换为 Python 3 的key 函数

参数:func 是比较函数(接受两个参数,返回负数/零/正数)。

使用场景:在 sorted() 中使用旧版比较逻辑。

from functools import cmp_to_key

def compare(a, b):
    return (a > b) - (a < b)  # 标准 cmp 函数

numbers = [5, 2, 8, 1]
sorted_nums = sorted(numbers, key=cmp_to_key(compare))
print(sorted_nums)  # 输出: [1, 2, 5, 8]

# 逆序比较
def reverse_cmp(a, b):
    return (b > a) - (b < a)

sorted_reverse = sorted(numbers, key=cmp_to_key(reverse_cmp))
print(sorted_reverse)  # 输出: [8, 5, 2, 1]

12.functools.cache()

功能:lru_cache(maxsize=None) 的快捷方式,创建无限制缓存的装饰器。

注意:Python 3.9+ 引入,等价于 @lru_cache(maxsize=None)。

使用场景:需要永久缓存结果的场景(如纯函数计算)。

from functools import cache

@cache
def factorial(n):
    return n * factorial(n-1) if n else 1

print(factorial(10))  # 输出: 3628800
print(factorial.cache_info())  # 输出: CacheInfo(hits=..., misses=..., maxsize=None, currsize=11)
© 版权声明

相关文章

1 条评论

  • 头像
    我美式ga 投稿者

    收藏了,感谢分享

    无记录
    回复