Python functools 模組常用工具教學 | Python

2026/04/24

Pythonfunctools 模組提供了多種處理函式的高階工具,包括快取、偏函式、歸約運算等。善用這些工具,可以大幅提升程式的效能與可讀性。本文將帶你認識 functools 中最常用的幾個函式。

什麼是 functools?

functoolsPython 標準函式庫中專門用於操作函式的模組。它提供的工具可以讓你對函式進行包裝、快取、組合等進階操作。使用前需要先匯入:

import functools

lru_cache:用快取加速遞迴

lru_cache 是一個裝飾器(Decorator),可以自動快取函式的回傳值。當相同的參數再次傳入時,直接回傳快取結果,省去重複計算的時間。LRU 代表 Least Recently Used(最近最少使用),超出快取上限時會自動移除最久未使用的結果。

以經典的費波那契數列(Fibonacci)為例:

from functools import lru_cache

# 沒有快取的版本(非常慢)
def fib_slow(n):
    if n < 2:
        return n
    return fib_slow(n - 1) + fib_slow(n - 2)

# 使用 lru_cache 的版本(極快)
@lru_cache(maxsize=128)
def fib_fast(n):
    if n < 2:
        return n
    return fib_fast(n - 1) + fib_fast(n - 2)

print(fib_fast(50))
# 輸出:12586269025

# 查看快取統計
print(fib_fast.cache_info())
# 輸出:CacheInfo(hits=48, misses=51, maxsize=128, currsize=51)

沒有快取時,fib_slow(50) 需要數兆次運算;有了 lru_cache,只需計算 51 次就能完成。

partial:建立偏函式

partial 可以將一個函式的部分參數預先固定,產生一個新的函式。這在需要重複使用相同參數時特別方便:

from functools import partial

# 將 int() 的 base 參數固定為 2,建立二進位轉換函式
int_from_binary = partial(int, base=2)
print(int_from_binary("1010"))   # 輸出:10
print(int_from_binary("1111"))   # 輸出:15

# 建立一個固定乘數的函式
def multiply(x, y):
    return x * y

double = partial(multiply, 2)
triple = partial(multiply, 3)

print(double(5))   # 輸出:10
print(triple(5))   # 輸出:15

reduce:歸約運算

reduce 會將一個二元函式依序套用在可迭代物件的元素上,逐步累積成一個結果。它的概念是「把一串值歸約成單一值」:

from functools import reduce

# 計算 1 到 5 的總和
result = reduce(lambda a, b: a + b, [1, 2, 3, 4, 5])
print(result)  # 輸出:15

# 計算階乘(5!)
factorial = reduce(lambda a, b: a * b, range(1, 6))
print(factorial)  # 輸出:120

# 找出最大值
numbers = [34, 12, 89, 45, 67]
max_val = reduce(lambda a, b: a if a > b else b, numbers)
print(max_val)  # 輸出:89

reduce 的執行過程是:先取前兩個元素計算,再用結果與第三個元素計算,依此類推,直到所有元素處理完畢。

wraps:保留裝飾器中的函式資訊

當你撰寫裝飾器時,被裝飾的函式會失去原本的名稱與文件字串(Docstring)。wraps 可以幫你保留這些原始資訊:

from functools import wraps

# 沒有使用 wraps
def my_decorator_bad(func):
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs)
    return wrapper

# 使用 wraps 保留原始函式資訊
def my_decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        """wrapper 的文件"""
        print("函式執行前")
        result = func(*args, **kwargs)
        print("函式執行後")
        return result
    return wrapper

@my_decorator
def greet(name):
    """打招呼的函式"""
    print(f"Hello, {name}!")

greet("Alice")
# 輸出:
# 函式執行前
# Hello, Alice!
# 函式執行後

print(greet.__name__)  # 輸出:greet(而非 wrapper)
print(greet.__doc__)   # 輸出:打招呼的函式

total_ordering:簡化比較方法

定義自訂類別時,如果想支援所有比較運算(<<=>>=),通常需要實作四個方法。使用 total_ordering 裝飾器,只需定義 __eq__ 和任一個比較方法,其餘的會自動補全:

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("小明", 85)
s2 = Student("小華", 92)

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

總結

functools 模組為 Python 開發者提供了許多實用的函式工具。本文介紹了 lru_cache(快取加速)、partial(偏函式)、reduce(歸約運算)、wraps(保留裝飾器資訊)以及 total_ordering(簡化比較方法)。這些工具能幫助你寫出更高效、更優雅的程式碼。希望這篇文章能幫助你在實際專案中靈活運用 functools 模組。

如果你想深入了解裝飾器的基本概念,請參考 Python 裝飾器教學

關於 Lambda 與高階函式的用法,請閱讀 Python Lambda 與高階函式教學