__enter__- og __exit__-protokollen
Opret context managers ved hjælp af dunder-protokollen.
__enter__- og __exit__-protokollen er en gratis Python Academy-lektion på CoddyKit. Dette er lektion 2 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i Python Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Python Academy-kurset indeholder 4 lektioner i alt.
Protokollen for konteksthåndterere
Ethvert objekt, der definerer __enter__ og __exit__, er en konteksthåndterer og kan bruges sammen 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")Returneringsværdi fra __enter__
__enter__ kaldes i starten af with-blokken. Dens returneringsværdi bindes til variablen efter 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) # 42Argumenter til __exit__
__exit__(exc_type, exc_val, exc_tb) modtager oplysninger om undtagelsen, hvis der opstod en fejl. Hvis der ikke er nogen undtagelse, 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") # suppressedUndertrykke undtagelser
Returnér True fra __exit__ for at undertrykke undtagelsen. Returnér False (eller ingenting) for at lade den blive videresendt.
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 anvendelsestilfælde: Hent en forbindelse ved start, gennemfør eller rul tilbage, og luk ved afslutning.
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 FalseEn timer som konteksthåndterer
Mål den forløbne tid ved at registrere starten i __enter__ og beregne forskellen 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))Indlejring af konteksthåndterere
Flere konteksthåndterere kan kombineres på en enkelt with-linje.
with open("in.txt") as src, open("out.txt", "w") as dst:
dst.write(src.read())Genbrugelige kontra engangs-konteksthåndterere
Konteksthåndterere, hvis __enter__ tildeler en ny ressource hver gang, kan genbruges. Dem, der opbruger en intern tilstand (som en lås, der kun holdes én gang), kan muligvis ikke genbruges.
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__ (asynkrone)
For asynkrone konteksthåndterere skal du definere koroutinerne __aenter__ og __aexit__ og bruge 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:
# ...Indpakning af filobjekter
Pythons filobjekter implementerer allerede protokollen for konteksthåndterere — kald aldrig f.close() manuelt.
with open("data.txt", "r") as f:
data = f.read()
# file is closed here automatically
print(f.closed) # TrueImplementere en lås
Trådlåse er konteksthåndterere: __enter__ erhverver låsen, og __exit__ frigiver den.
import threading
lock = threading.Lock()
def update_shared():
with lock:
# critical section
passHurtigt tjek
Hvad skal __exit__ returnere for at undertrykke en undtagelse?
Opsummering
Implementér __enter__ og __exit__ for at oprette kontekstmanagere. Returnér ressourcen fra __enter__, og håndtér oprydning og undertrykkelse af undtagelser i __exit__.
Lær Python med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 76
- Lektioner
- 320
Ofte stillede spørgsmål
Er lektionen “__enter__- og __exit__-protokollen” gratis?
Ja — hele teksten til “__enter__- og __exit__-protokollen” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af Python Academy-kurset, skal du opgradere til CoddyKit PRO. Python Academy-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “__enter__- og __exit__-protokollen”?
Opret context managers ved hjælp af dunder-protokollen. Du øver dig i Python Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på Python Academy?
Der kræves ingen tidligere erfaring. Python Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 2 af 4.
Hvor lang tid tager lektionen “__enter__- og __exit__-protokollen”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne Python Academy-lektion?
Ja. Alle Python Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- with-sætningen i dybden
- __enter__- og __exit__-protokollen
- contextlib: @contextmanager
- Praktiske mønstre for context managers