CodeWalk

functools高级工具:partial/partialmethod/cached_property/singledispatch/lru_cache

作者:我还是少年 · 2026-05-30 12:55

请详细说明functools模块中以下高级函数的用法和原理:

  1. partialpartialmethod的区别
  2. cached_property(Python 3.8+)的实现机制
  3. lru_cachecache(Python 3.9+)的性能差异
  4. singledispatchsingledispatchmethod实现多分派
  5. reduce在复杂累加场景中的使用

给出使用partialmethod冻结类方法的示例。

回答

我还是少年

partial vs partialmethod

from functools import partial, partialmethod

# partial:冻结函数参数
import math
log_base2 = partial(math.log, base=2)
log_base2(16)  # 4.0

# partialmethod:冻结类方法参数
class Window:
    def __init__(self):
        self.width = 800
        self.height = 600
    
    def resize(self, width, height):
        self.width = width
        self.height = height
    
    double_width = partialmethod(resize, height=600)  # 冻结height
    
win = Window()
win.double_width(1600)  # width=1600, height=600

cached_property

from functools import cached_property

class DataProcessor:
    @cached_property
    def heavy_computation(self):
        time.sleep(5)  # 第一次计算并缓存
        return sum(range(10**7))

# 首次访问计算,后续直接返回缓存值
# 与@property不同:值存储在实例__dict__中,可被清除

lru_cache vs cache

from functools import lru_cache, cache

@lru_cache(maxsize=128)
def fib(n):
    return n if n < 2 else fib(n-1) + fib(n-2)

@cache  # Python 3.9+,等价于 lru_cache(maxsize=None)
def factorial(n):
    return n * factorial(n-1) if n else 1

cache无限大,适合参数空间有限的纯函数

singledispatch

from functools import singledispatch

@singledispatch
def serialize(obj):
    raise TypeError(f'Unsupported type: {type(obj)}')

@serialize.register(int)
def _(obj):
    return str(obj)

@serialize.register(list)
def _(obj):
    return ','.join(str(x) for x in obj)

@serialize.register(dict)
def _(obj):
    import json
    return json.dumps(obj)

reduce高级用法:实现像itertools.accumulate一样累加但返回最终值,或实现min/max

from functools import reduce
reduce(lambda a, b: a if a > b else b, [3, 1, 4, 1, 5, 9])  # 9