Python Academy · leksjon

functools: lru_cache og cached_property

Bufre kostbare beregninger med lru_cache og cached_property.

Leksjon 4 av 413 trinn

functools: lru_cache og cached_property er en gratis leksjon i Python Academy på CoddyKit. Dette er leksjon 4 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Python Academy, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Python Academy inneholder totalt 4 leksjoner.

Hva er memoisering?

Memoisering mellomlagrer resultatet av et funksjonskall med argumentene som nøkkel. Gjentatte kall med de samme argumentene returnerer det mellomlagrede resultatet umiddelbart.

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) mellomlagrer opptil maxsize nylige resultater. Angi maxsize=None for en cache uten størrelsesbegrensning.

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 er en kortform for lru_cache(maxsize=None) — en cache uten størrelsesbegrensning og med et enklere navn.

import functools

@functools.cache
def factorial(n):
    return n * factorial(n-1) if n else 1

print(factorial(10))  # 3628800

Cacheinformasjon og tømming

Funksjoner med cache tilbyr .cache_info() (treff, bom, størrelse) og .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()

LRU-fjerningspolicy

LRU (Least Recently Used) fjerner elementet som sist ble brukt minst, når cachen er full.

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)

Bare hashbare argumenter

lru_cache krever at alle argumenter er hashbare. Lister og ordbøker er ikke hashbare; bruk tupler i stedet.

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 beregner en property én gang og mellomlagrer resultatet på instansen, slik at deskriptoren erstattes med verdien.

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 kontra property

@property beregner verdien på nytt ved hvert oppslag. @cached_property beregner den én gang og lagrer resultatet i 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))

Trådsikkerhet for cached_property

cached_property er ikke trådsikker. Hvis flere tråder får tilgang samtidig, kan beregningen kjøres mer enn én gang. Bruk en lås ved behov.

import functools, threading

class SafeCache:
    _lock = threading.Lock()

    @functools.cached_property
    def data(self):
        with self._lock:
            return expensive_computation()

Ugyldiggjøre cached_property

Slett instansattributtet for å ugyldiggjøre cachen og tvinge frem en ny beregning ved neste oppslag.

import functools

class Report:
    @functools.cached_property
    def summary(self):
        return compute_summary()

r = Report()
_ = r.summary      # computed
del r.summary      # invalidate
_ = r.summary      # recomputed

Bruke lru_cache som API-cache

Mellomlagre API-svar for en økt for å unngå overflødige nettverkskall. Tøm cachen når De trenger oppdaterte data.

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)   # cached

Hurtigsjekk

Hvilken metode tømmer alle mellomlagrede resultater for en funksjon dekorert med @lru_cache?

Oppsummering

@lru_cache mellomlagrer funksjonsresultater basert på argumentene (som må være hashbare). @cache er et alias uten størrelsesbegrensning. @cached_property mellomlagrer beregningen av en property per instans. Undersøk med cache_info(), og tilbakestill med cache_clear().

Gratis å komme i gang

Lær deg Python med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
76
Leksjoner
320

Ofte stilte spørsmål

Er leksjonen «functools: lru_cache og cached_property» gratis?

Ja – hele teksten i «functools: lru_cache og cached_property» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av Python Academy-kurset, kan du oppgradere til CoddyKit PRO. Kurset i Python Academy inneholder totalt 4 leksjoner.

Hva lærer jeg i «functools: lru_cache og cached_property»?

Bufre kostbare beregninger med lru_cache og cached_property. Du øver på Python Academy med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med Python Academy?

Ingen tidligere erfaring er nødvendig. Python Academy på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 4 av 4.

Hvor lang tid tar leksjonen «functools: lru_cache og cached_property»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne Python Academy-leksjonen?

Ja. Alle Python Academy-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. itertools: Uendelige og endelige iteratorer
  2. itertools: Kombinatorikk
  3. functools: partial og reduce
  4. functools: lru_cache og cached_property
← Tilbake til Python Academy