functools: lru_cache i cached_property
Proszę buforować kosztowne obliczenia za pomocą lru_cache i cached_property.
functools: lru_cache i cached_property to bezpłatna lekcja Python Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Python Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Python Academy zawiera 4 lekcji w sumie.
Czym jest memoizacja?
Memoizacja przechowuje wynik wywołania funkcji pod kluczem utworzonym z jej argumentów. Kolejne wywołania z tymi samymi argumentami natychmiast zwracają wynik z pamięci podręcznej.
def slow_fib(n):
if n < 2: return n
return slow_fib(n-1) + slow_fib(n-2)
# slow_fib(35) makes ~29 million calls
# With caching it makes only 35@lru_cache
@functools.lru_cache(maxsize=128) przechowuje w pamięci podręcznej do maxsize ostatnich wyników. Ustawienie maxsize=None tworzy cache bez ograniczenia rozmiaru.
import functools
@functools.lru_cache(maxsize=None)
def fib(n):
if n < 2: return n
return fib(n-1) + fib(n-2)
print(fib(50)) # instant@cache — Python 3.9+
functools.cache to skrócona forma lru_cache(maxsize=None) — nieograniczona pamięć podręczna o czytelniejszej nazwie.
import functools
@functools.cache
def factorial(n):
return n * factorial(n-1) if n else 1
print(factorial(10)) # 3628800Informacje o pamięci podręcznej i jej czyszczenie
Funkcje z pamięcią podręczną udostępniają metody .cache_info() (trafienia, chybienia, rozmiar) oraz .cache_clear().
import functools
@functools.lru_cache(maxsize=100)
def square(n):
return n * n
for i in range(5): square(i % 3)
print(square.cache_info())
# CacheInfo(hits=2, misses=3, maxsize=100, currsize=3)
square.cache_clear()Zasada usuwania LRU
LRU (Least Recently Used) usuwa element, do którego najdawniej uzyskano dostęp, gdy pamięć podręczna jest pełna.
import functools
@functools.lru_cache(maxsize=3)
def compute(n):
print(f"computing {n}")
return n**2
for x in [1,2,3,4,1]: # 4 evicts 1 (LRU), then 1 re-computes
compute(x)Tylko argumenty haszowalne
lru_cache wymaga, aby wszystkie argumenty były haszowalne. Listy i słowniki nie są haszowalne, dlatego należy używać krotek.
import functools
@functools.lru_cache(maxsize=None)
def sum_tuple(t): # tuple is hashable
return sum(t)
print(sum_tuple((1,2,3))) # 6
# sum_tuple([1,2,3]) # TypeError@cached_property
functools.cached_property oblicza właściwość raz i zapisuje wynik w instancji, zastępując deskryptor wartością.
import functools
class Circle:
def __init__(self, r):
self.r = r
@functools.cached_property
def area(self):
import math
print("computing...")
return math.pi * self.r ** 2
c = Circle(5)
print(c.area) # computing... 78.53...
print(c.area) # 78.53... (cached, no print)cached_property a property
@property ponownie oblicza wartość przy każdym dostępie. @cached_property oblicza ją raz i zapisuje wynik w instance.__dict__.
import functools
class Expensive:
@property
def always(self): # runs every access
return sum(range(1_000_000))
@functools.cached_property
def once(self): # runs only first access
return sum(range(1_000_000))Bezpieczeństwo wątkowe cached_property
cached_property nie jest bezpieczne wątkowo. Jeśli wiele wątków uzyska do niego dostęp jednocześnie, obliczenie może zostać wykonane więcej niż raz. W razie potrzeby należy użyć blokady.
import functools, threading
class SafeCache:
_lock = threading.Lock()
@functools.cached_property
def data(self):
with self._lock:
return expensive_computation()Unieważnianie cached_property
Aby unieważnić pamięć podręczną i wymusić ponowne obliczenie przy następnym dostępie, należy usunąć atrybut instancji.
import functools
class Report:
@functools.cached_property
def summary(self):
return compute_summary()
r = Report()
_ = r.summary # computed
del r.summary # invalidate
_ = r.summary # recomputedUżywanie lru_cache jako pamięci podręcznej API
Odpowiedzi API można przechowywać w pamięci podręcznej na czas sesji, aby uniknąć zbędnych wywołań sieciowych. Pamięć podręczną należy wyczyścić, gdy potrzebne są aktualne dane.
import functools, urllib.request, json
@functools.lru_cache(maxsize=32)
def get_user(user_id):
url = f"https://api.example.com/users/{user_id}"
with urllib.request.urlopen(url) as r:
return json.loads(r.read())
user = get_user(42) # network call
user = get_user(42) # cachedSzybkie sprawdzenie
Jaka metoda usuwa wszystkie wyniki z pamięci podręcznej funkcji udekorowanej za pomocą @lru_cache?
Podsumowanie
@lru_cache przechowuje wyniki funkcji pod kluczami utworzonymi z argumentów, które muszą być haszowalne. @cache jest aliasem bez ograniczenia rozmiaru. @cached_property przechowuje wynik obliczenia właściwości osobno dla każdej instancji. Stan można sprawdzić za pomocą cache_info(), a pamięć zresetować za pomocą cache_clear().
Często zadawane pytania
Czy lekcja „functools: lru_cache i cached_property” jest bezpłatna?
Tak — pełny tekst „functools: lru_cache i cached_property” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Python Academy, przejdź na CoddyKit PRO. Kurs Python Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „functools: lru_cache i cached_property”?
Proszę buforować kosztowne obliczenia za pomocą lru_cache i cached_property. Ćwiczysz Python Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Python Academy?
Nie wymagamy żadnego doświadczenia. Python Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.
Ile czasu zajmuje lekcja „functools: lru_cache i cached_property”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Python Academy?
Tak. Każda lekcja Python Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- itertools: iteratory nieskończone i skończone
- itertools: kombinatoryka
- functools: partial i reduce
- functools: lru_cache i cached_property