
functools.lru_cache: จำผลคำนวณซ้ำโดยไม่ต้องเขียนแคชเอง
น้องกายEngineering
เคยเรียกฟังก์ชันเดิมด้วยอินพุตเดิมซ้ำๆ แล้วเสียเวลารอไหม ผมเคย จนใช้ functools.lru_cache
ตามเอกสาร functools ของ Python เดคอเรเตอร์นี้เก็บผลลัพธ์ตามอาร์กิวเมนต์แบบ LRU (Least Recently Used) เมื่อเต็ม maxsize จะไล่รายการที่ไม่ได้ใช้ล่าสุดออก
เลือกยังไงสั้นๆ
- ใส่
@lru_cacheเมื่อฟังก์ชันบริสุทธิ์ (ผลขึ้นกับอินพุตอย่างเดียว) และถูกเรียกซ้ำบ่อย - ตั้ง
maxsizeให้พอดีกับชุดอินพุตที่ซ้ำจริง;maxsize=Noneคือแคชไม่จำกัดขนาด - อาร์กิวเมนต์ต้องแฮชได้ (hashable) เช่น
int/str/tupleไม่ใช่list/dict - ดูสถิติด้วย
.cache_info()และล้างด้วย.cache_clear()ตอนเทสต์หรือหลังข้อมูลต้นทางเปลี่ยน
from functools import lru_cache
@lru_cache(maxsize=2)
def square(n: int) -> int:
return n * n
assert square(3) == 9
assert square(3) == 9
info = square.cache_info()
assert info.hits == 1 and info.misses == 1 and info.currsize == 1
square(4)
square(5) # maxsize=2 จึงไล่รายการเก่าออกเมื่อเต็ม
assert square.cache_info().currsize == 2
square.cache_clear()
assert square.cache_info().currsize == 0
print("ok")
Recap
- ใช้
lru_cacheกับฟังก์ชันบริสุทธิ์ที่ถูกเรียกซ้ำ - เลือก
maxsizeตามชุดอินพุตจริง ไม่เดาจากความรู้สึก - ตรวจว่าอาร์กิวเมนต์แฮชได้ก่อนครอบเดคอเรเตอร์
- ใส่
cache_clear()ในเทสต์เมื่อสเตตต้นทางเปลี่ยน