Python itertools 與 functools 高階工具

在 Python 的世界裡,函數與迭代器是一等公民。itertoolsfunctools 模組提供了眾多高階工具,讓我們能以「函數式編程」的風格寫出更簡潔、更高效的程式碼。

itertools 模組:迭代器工具

itertools 提供的工具都是「惰性求值」(Lazy Evaluation),這意味著它們只在需要時才計算下一個值,非常省記憶體。

無限迭代與重複

import itertools

# count: 從 N 開始無限計數
# for i in itertools.count(10): print(i)

# cycle: 無限循環一個序列
colors = itertools.cycle(['紅', '綠', '藍'])
print(next(colors)) # 紅
print(next(colors)) # 綠

# repeat: 重複同一個物件
# itertools.repeat('Hello', 3)

組合與排列 (面試常考!)

import itertools

items = ['A', 'B', 'C']

# 排列 (Permutations): 考慮順序
print(list(itertools.permutations(items, 2)))
# [('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'C'), ('C', 'A'), ('C', 'B')]

# 組合 (Combinations): 不考慮順序
print(list(itertools.combinations(items, 2)))
# [('A', 'B'), ('A', 'C'), ('B', 'C')]

# 笛卡兒積 (Product): 多個集合的交叉組合
nums = [1, 2]
print(list(itertools.product(items, nums)))
# [('A', 1), ('A', 2), ('B', 1), ('B', 2), ('C', 1), ('C', 2)]

序列處理

  • itertools.chain(): 將多個列表串聯成一個連續的迭代器。
  • itertools.islice(): 像切片一樣切割迭代器(但不耗盡整個迭代器)。

functools 模組:高階函數工具

functools 專門用於處理函數,特別是「函數裝飾器」與「偏函數」。

lru_cache:自動記憶化 (Caching)

這是一個極度強大的裝飾器,可以快取函數的執行結果。如果用同樣的參數再次呼叫,會直接從記憶體拿結果,特別適合用於遞迴或昂貴運算。

from functools import lru_cache

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

print(fibonacci(50)) # 瞬間完成!

partial:偏函數

partial 讓你可以預先固定函數的部分參數,產生一個新的函數。

from functools import partial

def multiply(x, y):
    return x * y

# 創建一個專門「乘以 2」的函數
double = partial(multiply, 2)

print(double(10)) # 20
print(double(5))  # 10

wraps:保留原始函數屬性

寫裝飾器時,如果不使用 wraps,被裝飾的函數會「丟失」它的原始名稱 (__name__) 與文檔字串。

from functools import wraps

def my_logger(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        print(f"呼叫 {func.__name__}...")
        return func(*args, **kwargs)
    return wrapper

@my_logger
def hello():
    """這是一個問候函數"""
    print("Hello!")

print(hello.__name__) # hello (若沒加 wraps 會變成 wrapper)

總結

  • itertools:當你需要複雜的迴圈邏輯、排列組合、或處理海量數據迭代時,它是首選。
  • functools:當你需要優化函數效能 (lru_cache)、簡化參數調用 (partial)、或撰寫標準化的裝飾器 (wraps) 時,它是必備工具。

掌握這兩個模組,能讓你的 Python 代碼脫胎換骨,從「會寫」進階到「寫得優雅」。