随着我们在 Python 世界里编织出越来越复杂的程序,经常会发现自己在不停地重复相同的操作:一次又一次地调用同一个函数、使用同样的输入、执行相同的计算……就像一台忘了自己昨天做过什么的机器,白白浪费了宝贵的算力和时间。

好在,Python 的 functools 模块来拯救我们了。它内置了一系列“高阶工具”,帮你在不改动函数本身的前提下,轻松重用逻辑、提升可读性、压榨性能。下面,就让我带你逐个揭秘,这些轻量级宝藏该怎么用。


从“记忆”开始:lru_cache

想象一下:每次你算完一个结果,都留个“备份”,下次再遇到同样的输入,就直接抄作业,不必重头演算。lru_cache(Least Recently Used 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(35))
  • maxsize 决定“作业本”能写多少条记录,设置为 None 则无限制。
  • 对于经典的递归、频繁的 API 调用、耗时的数据库查询,它能让运行速度从“分”级骤降到“毫秒”级秒杀。

一行搞定聚合:reduce

要把一长串数据一口气“压缩”为一个值,最直观的做法是写个 for 循环。可若你想写得更简洁、更函数式,reduce() 就能派上用场:

from functools import reduce

numbers = [2, 3, 4]
result = reduce(lambda x, y: x * y, numbers)
print(result)  # 输出 24

它依次拿出 x, y,应用你给的函数,一直“合并”到只剩下一个结果。写成一行,逻辑一目了然,也少了样板式的循环变量。


装饰器的“身份证”:wraps

自己动手写装饰器,往往会遗失原函数的名字和文档(__doc__)。这样一来,调试和自动化文档就会闹乌龙。只要在 wrapper 上加个 @wraps(func),身份就能照单全收:

from functools import wraps

def my_decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        # ……插入前置或后置逻辑……
        return func(*args, **kwargs)
    return wrapper

@my_decorator
def greet():
    """简单说声你好"""
    print("Hello!")

print(greet.__name__)  # 仍然是 "greet"
print(greet.__doc__)   # "简单说声你好"

这样,不管你套了多少层装饰,函数依旧“我行我素”,不改身份证,调试更轻松,文档更靠谱。


预设参数神器:partial

有时候,你写了个通用函数,频繁需要“锁定”几个参数再复用——这时 partial 就好比给你的函数做了“微调”,输出一版定制版本:

from functools import partial

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

square = partial(power, exponent=2)
cube   = partial(power, exponent=3)

print(square(5))  # 25
print(cube(2))    # 8
  • square(5) 底层其实跑的是 power(5, 2)cube(2) 则是 power(2, 3)
  • 用在 mapfilter、回调函数里,更显简洁与优雅。

更简单的缓存:cache(Python 3.9+)

如果你用的是 3.9 及以上版本,想要无限制缓存,只要一个更简洁的写法:

from functools import cache

@cache
def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n - 1) + fibonacci(n - 2)

等同于 @lru_cache(maxsize=None),让纯函数的天堂更纯粹。


一键补全比较:total_ordering

给类写比较方法,少不了 __lt____gt____eq__……多达六个。如果你只想定义“等于”+“小于”,就用 @total_ordering 让它自动生成剩下的:

from functools import total_ordering

@total_ordering
class Book:
    def __init__(self, title, pages):
        self.title = title
        self.pages = pages

    def __eq__(self, other):
        return self.pages == other.pages

    def __lt__(self, other):
        return self.pages < other.pages

b1 = Book("深度思考", 200)
b2 = Book("高效学习", 300)
print(b1 < b2)   # True
print(b1 >= b2)  # False

如此一来,<=, >, >=, !=……都由 total_ordering 自动搞定,类定义清爽又易维护。


小结:让代码更聪明一点

  • 速度提升lru_cachecache 一键记忆,省去重复计算。
  • 简洁优雅partialreduce 让逻辑高度抽象,一行搞定循环或参数预设。
  • 可维护性wraps 保留函数元信息,total_ordering 自动补全比较套件。

别小看这些“轻量工具”,它们能让你的 Python 代码更简练、更高效、更易读。下次再敲那些重复逻辑时,不妨先想想:functools 有没有更优雅的解决方案?


作者寄语
如果这篇教程对你有所帮助,欢迎关注和留言。未来我还会分享更多 Python 深度技巧与实战心得,咱们下次见!

– END –