นากกายวางกล่องผลลัพธ์ซ้ำบนชั้นแคชขนาดจำกัดบนโต๊ะมิ้นต์

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

  1. ใช้ lru_cache กับฟังก์ชันบริสุทธิ์ที่ถูกเรียกซ้ำ
  2. เลือก maxsize ตามชุดอินพุตจริง ไม่เดาจากความรู้สึก
  3. ตรวจว่าอาร์กิวเมนต์แฮชได้ก่อนครอบเดคอเรเตอร์
  4. ใส่ cache_clear() ในเทสต์เมื่อสเตตต้นทางเปลี่ยน