med uttalelse i Python

I Python, med uttalelse brukes i unntakshåndtering for å gjøre koden renere og mye mer lesbar. Det forenkler administrasjonen av vanlige ressurser som filstrømmer. Se følgende kodeeksempel på hvordan bruken av with statement gjør koden renere.

Python3




# file handling> # 1) without using with statement> file> => open> (> 'file_path'> ,> 'w'> )> file> .write(> 'hello world !'> )> file> .close()> # 2) without using with statement> file> => open> (> 'file_path'> ,> 'w'> )> try> :> > file> .write(> 'hello world'> )> finally> :> > file> .close()>

Python3




# using with statement> with> open> (> 'file_path'> ,> 'w'> ) as> file> :> > file> .write(> 'hello world !'> )>

Legg merke til at i motsetning til de to første implementeringene, er det ikke nødvendig å kalle file.close() når du bruker med setning. Med-erklæringen i seg selv sikrer riktig anskaffelse og frigjøring av ressurser. Et unntak under file.write()-kallet i den første implementeringen kan forhindre at filen lukkes ordentlig, noe som kan introdusere flere feil i koden, dvs. mange endringer i filer trer ikke i kraft før filen er ordentlig lukket. Den andre tilnærmingen i eksemplet ovenfor tar seg av alle unntakene, men bruk av with-setningen gjør koden kompakt og mye mer lesbar. Dermed hjelper med uttalelse å unngå feil og lekkasjer ved å sikre at en ressurs er riktig utgitt når koden som bruker ressursen er fullstendig utført. With-setningen er populært brukt med filstrømmer, som vist ovenfor og med låser, sockets, underprosesser og telnets etc.

Støtter with-setningen i brukerdefinerte objekter

Det er ikke noe spesielt i open() som gjør det brukbart med with-setningen, og den samme funksjonaliteten kan leveres i brukerdefinerte objekter. Støtte med uttalelse i objektene dine vil sikre at du aldri lar noen ressurs være åpen. For å bruke med setning i brukerdefinerte objekter trenger du bare å legge til metodene __enter__() og __exit__() i objektmetodene. Tenk på følgende eksempel for ytterligere avklaring.

Python3




# a simple file writer object> class> MessageWriter(> object> ):> > def> __init__(> self> , file_name):> > self> .file_name> => file_name> > > def> __enter__(> self> ):> > self> .> file> => open> (> self> .file_name,> 'w'> )> > return> self> .> file> > def> __exit__(> self> ,> *> args):> > self> .> file> .close()> # using with statement with MessageWriter> with MessageWriter(> 'my_file.txt'> ) as xfile:> > xfile.write(> 'hello world'> )>

La oss undersøke koden ovenfor. Hvis du legger merke til, er det som følger nøkkelordet with konstruktøren av MessageWriter. Så snart utførelsen kommer inn i konteksten til with-setningen, opprettes et MessageWriter-objekt og python kaller deretter __enter__()-metoden. I denne __enter__()-metoden initialiserer du ressursen du ønsker å bruke i objektet. Denne __enter__()-metoden skal alltid returnere en beskrivelse av den innhentede ressursen. Hva er ressursbeskrivelser? Dette er håndtakene som leveres av operativsystemet for å få tilgang til de forespurte ressursene. I den følgende kodeblokken er filen en beskrivelse av filstrømressursen.

Python




file> => open> (> 'hello.txt'> )>

I MessageWriter-eksemplet ovenfor, oppretter __enter__()-metoden en filbeskrivelse og returnerer den. Navnet xfile her brukes for å referere til filbeskrivelsen som returneres av __enter__()-metoden. Kodeblokken som bruker den innhentede ressursen er plassert inne i blokken til with-setningen. Så snart koden inne i with-blokken er utført, kalles __exit__()-metoden. Alle de innhentede ressursene frigis i __exit__()-metoden. Dette er hvordan vi bruker with-setningen med brukerdefinerte objekter. Dette grensesnittet til __enter__() og __exit__() metodene som gir støtte for med uttalelse i brukerdefinerte objekter kalles Kontekstbehandling .

Contextlib-modulen

En klassebasert kontekstbehandling som vist ovenfor er ikke den eneste måten å støtte with-setningen i brukerdefinerte objekter. De kontekstlib modulen gir noen flere abstraksjoner bygget på det grunnleggende kontekstbehandlingsgrensesnittet. Her er hvordan vi kan omskrive kontekstbehandlingen for MessageWriter-objektet ved å bruke contextlib-modulen.

Python3




from> contextlib> import> contextmanager> class> MessageWriter(> object> ):> > def> __init__(> self> , filename):> > self> .file_name> => filename> > @contextmanager> > def> open_file(> self> ):> > try> :> > file> => open> (> self> .file_name,> 'w'> )> > yield> file> > finally> :> > file> .close()> # usage> message_writer> => MessageWriter(> 'hello.txt'> )> with message_writer.open_file() as my_file:> > my_file.write(> 'hello world'> )>

I dette kodeeksemplet, på grunn av utbytte setningen i sin definisjon, er funksjonen open_file() en generator funksjon . Når denne open_file()-funksjonen kalles, oppretter den en ressursbeskrivelse kalt fil. Denne ressursbeskrivelsen sendes deretter til den som ringer og er representert her av variabelen min_fil. Etter at koden i with-blokken er utført, går programkontrollen tilbake til funksjonen open_file(). Open_file()-funksjonen gjenopptar kjøringen og kjører koden etter yield-setningen. Denne delen av koden som vises etter at avkastningserklæringen frigir de innhentede ressursene. @contextmanageren her er en dekoratør . Den tidligere klassebaserte implementeringen og denne generatorbaserte implementeringen av kontekstledere er internt den samme. Mens det senere virker mer lesbart, krever det kunnskap om generatorer, dekoratører og utbytte.