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
hva er forskjellen mellom en megabyte og en gigabyte
# 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
konvertere boolesk til streng
# 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.
java strengbygger
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
java array liste
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.