計數器需在多次呼叫間保持狀態。閉包捕獲外部變數實現「帶狀態的函數」。Python 2 用列表繞過賦值限制,Python 3 直接用 nonlocal。
def generate_counter():
CNT = [0]
def add_one():
CNT[0] += 1
return CNT[0]
return add_one
counter = generate_counter()
print(counter()) # 1
print(counter()) # 2
print(counter()) # 3
def generate_counter():
count = 0
def add_one():
nonlocal count
count += 1
return count
return add_one
def make_counter(start=0, step=1):
count = start - step
def inc():
nonlocal count
count += step
return count
return inc
c1 = make_counter()
c2 = make_counter(100, 5)
print([c1() for _ in range(3)]) # [1, 2, 3]
print([c2() for _ in range(3)]) # [105, 110, 115]
import threading
def make_threadsafe_counter():
count = 0
lock = threading.Lock()
def inc():
nonlocal count
with lock:
count += 1
return count
return inc
閉包計數器簡潔優雅,是 Python 狀態封裝的經典範例。