Python Academy · Oppitunti

__enter__- ja __exit__-protokolla

Rakentakaa kontekstinhallitsijoita dunder-protokollan avulla.

Oppitunti 2/413 vaihetta

__enter__- ja __exit__-protokolla on ilmainen Python Academy-oppitunti CoddyKitissä. Tämä on oppitunti 2/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu Python Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Python Academy-kurssilla on yhteensä 4 oppituntia.

Kontekstinhallintaprotokolla

Kaikki oliot, jotka määrittelevät __enter__- ja __exit__-metodit, ovat kontekstinhallintaolioita ja niitä voidaan käyttää with-lausekkeiden kanssa.

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")

__enter__-metodin palautusarvo

__enter__ kutsutaan with-lohkon alussa. Sen palautusarvo sidotaan muuttujaan, joka tulee as-sanan jälkeen.

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

__exit__-metodin argumentit

__exit__(exc_type, exc_val, exc_tb) vastaanottaa poikkeustiedot, jos tapahtui virhe. Jos poikkeusta ei tapahtunut, kaikki kolme arvoa ovat 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

Poikkeusten vaientaminen

Palauttakaa True metodista __exit__, jos haluatte vaientaa poikkeuksen. Palauttakaa False tai älkää palauttako mitään, jos haluatte sen välittyvän eteenpäin.

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

with Ignore():
    1 / 0

print("continues here")

Esimerkki tietokantayhteydestä

Klassinen käyttötapaus: hankkikaa yhteys enter-vaiheessa, vahvistakaa muutokset tai perukaa ne ja sulkekaa yhteys exit-vaiheessa.

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

Ajastinkontekstinhallintaolio

Mit atkaa kulunut aika tallentamalla aloitushetki __enter__-metodissa ja laskemalla erotus __exit__-metodissa.

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

Kontekstinhallintaolioiden sisäkkäisyys

Useita kontekstinhallintaolioita voidaan yhdistää yhdelle with-riville.

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

Uudelleenkäytettävät ja kertakäyttöiset hallintaoliot

Kontekstinhallintaoliot, joiden __enter__ varaa joka kerta uuden resurssin, ovat uudelleenkäytettäviä. Oliot, joiden sisäinen tila kuluu loppuun — kuten vain kerran pidettävä lukko — eivät välttämättä ole uudelleenkäytettäviä.

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__ ja __aexit__ (asynkroninen)

Asynkronisia kontekstinhallintaolioita varten määritelkää __aenter__- ja __aexit__-korutiinit ja käyttäkää async with-lausetta.

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:
#     ...

Tiedosto-olioiden kääriminen

Pythonin tiedosto-oliot toteuttavat jo kontekstinhallintaprotokollan — älkää koskaan kutsuko f.close()-metodia manuaalisesti.

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

Lukon toteuttaminen

Säielukot ovat kontekstinhallintaolioita: __enter__ hankkii lukon ja __exit__ vapauttaa sen.

import threading

lock = threading.Lock()

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

Pikatarkistus

Mitä __exit__-metodin pitäisi palauttaa poikkeuksen vaimentamiseksi?

Kertaus

Toteuttakaa __enter__- ja __exit__-metodit kontekstinhallintojen luomiseksi. Palauttakaa resurssi metodista __enter__ ja huolehtikaa metodissa __exit__ siivouksesta sekä poikkeusten vaimentamisesta.

Aloita maksutta

Opi Python tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
76
Oppitunnit
320

Usein kysytyt kysymykset

Onko oppitunti ”__enter__- ja __exit__-protokolla” ilmainen?

Kyllä – oppitunnin ”__enter__- ja __exit__-protokolla” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko Python Academy-kurssin, päivitä CoddyKit PROhon. Python Academy-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”__enter__- ja __exit__-protokolla”?

Rakentakaa kontekstinhallitsijoita dunder-protokollan avulla. Harjoittelet Python Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni Python Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin Python Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 2/4.

Kuinka kauan ”__enter__- ja __exit__-protokolla”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä Python Academy-oppitunnilla?

Kyllä. Jokainen Python Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. with-lauseen perusteet
  2. __enter__- ja __exit__-protokolla
  3. contextlib: @contextmanager
  4. Käytännön kontekstinhallitsijamallit
← Takaisin: Python Academy