Python Academy · leksjon

__enter__- og __exit__-protokollen

Opprett kontekstbehandlere ved hjelp av dunder-protokollen.

Leksjon 2 av 413 trinn

__enter__- og __exit__-protokollen er en gratis leksjon i Python Academy på CoddyKit. Dette er leksjon 2 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.

Kontekstbehandlerprotokollen

Alle objekter som definerer __enter__ og __exit__, er kontekstbehandlere og kan brukes med with.

class Managed:
    def __enter__(self):
        print("entering")
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("exiting")
        return False

with Managed() as m:
    print("inside")

Returverdien til __enter__

__enter__ kalles i starten av with-blokken. Returverdien bindes til variabelen etter as.

class Resource:
    def __enter__(self):
        self.value = 42
        return self  # bound to 'r'

    def __exit__(self, *args):
        self.value = None
        return False

with Resource() as r:
    print(r.value)  # 42

Argumentene til __exit__

__exit__(exc_type, exc_val, exc_tb) mottar informasjon om unntaket hvis det oppstod en feil. Hvis det ikke oppstod noe unntak, er alle tre None.

class Safe:
    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        if exc_type is ValueError:
            print(f"Suppressed ValueError: {exc_val}")
            return True   # suppress the exception
        return False      # re-raise anything else

with Safe():
    raise ValueError("oops")  # suppressed

Undertrykke unntak

Returner True fra __exit__ for å undertrykke unntaket. Returner False (eller ingenting) for å la det videreføres.

class Ignore:
    def __enter__(self): return self
    def __exit__(self, *args): return True  # swallow all exceptions

with Ignore():
    1 / 0

print("continues here")

Et eksempel med en databaseforbindelse

Et klassisk bruksområde: Hent en forbindelse ved start, utfør commit eller rollback og lukk den ved avslutning.

class DBConn:
    def __enter__(self):
        self.conn = connect_db()
        return self.conn

    def __exit__(self, exc_type, exc_val, exc_tb):
        if exc_type:
            self.conn.rollback()
        else:
            self.conn.commit()
        self.conn.close()
        return False

En tidsmåler som kontekstbehandler

Mål medgått tid ved å registrere starttidspunktet i __enter__ og beregne differansen i __exit__.

import time

class Timer:
    def __enter__(self):
        self.start = time.perf_counter()
        return self

    def __exit__(self, *args):
        self.elapsed = time.perf_counter() - self.start
        print(f"Elapsed: {self.elapsed:.3f}s")
        return False

with Timer():
    sum(range(1_000_000))

Nesting av kontekstbehandlere

Flere kontekstbehandlere kan kombineres på én with-linje.

with open("in.txt") as src, open("out.txt", "w") as dst:
    dst.write(src.read())

Gjenbrukbare kontra engangsbehandlere

Kontekstbehandlere der __enter__ tildeler en ny ressurs hver gang, kan gjenbrukes. Behandlere som tømmer en intern tilstand (for eksempel en lås som bare holdes én gang), kan ikke nødvendigvis gjenbrukes.

class Reusable:
    def __enter__(self):
        return []
    def __exit__(self, *a):
        return False

for _ in range(3):
    with Reusable() as lst:
        lst.append(1)
        print(lst)  # [1] each time

__aenter__ og __aexit__ (asynkront)

For asynkrone kontekstbehandlere definerer De korutinene __aenter__ og __aexit__ og bruker async with.

class AsyncDB:
    async def __aenter__(self):
        self.conn = await connect()
        return self.conn

    async def __aexit__(self, *args):
        await self.conn.close()

# async with AsyncDB() as conn:
#     ...

Pakke inn filobjekter

Python-filobjekter implementerer allerede kontekstbehandlerprotokollen – kall aldri f.close() manuelt.

with open("data.txt", "r") as f:
    data = f.read()
# file is closed here automatically
print(f.closed)  # True

Implementere en lås

Trådlåser er kontekstbehandlere: __enter__ låser, og __exit__ låser opp.

import threading

lock = threading.Lock()

def update_shared():
    with lock:
        # critical section
        pass

Kunnskapssjekk

Hva må __exit__ returnere for å undertrykke et unntak?

Oppsummering

Implementer __enter__ og __exit__ for å opprette kontekstbehandlere. Returner ressursen fra __enter__, og håndter opprydding og undertrykking av unntak i __exit__.

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 «__enter__- og __exit__-protokollen» gratis?

Ja – hele teksten i «__enter__- og __exit__-protokollen» 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 «__enter__- og __exit__-protokollen»?

Opprett kontekstbehandlere ved hjelp av dunder-protokollen. 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 2 av 4.

Hvor lang tid tar leksjonen «__enter__- og __exit__-protokollen»?

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. with-setningen i dybden
  2. __enter__- og __exit__-protokollen
  3. contextlib: @contextmanager
  4. Praktiske mønstre for kontekstbehandlere
← Tilbake til Python Academy