I Python, med udsagn bruges i undtagelseshåndtering for at gøre koden renere og meget mere læsbar. Det forenkler styringen af fælles ressourcer som filstrømme. Bemærk følgende kodeeksempel om, hvordan brugen af with statement gør kode renere.
Python3
rihanna alder
# 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 !'>)> |
>
>
Bemærk, at i modsætning til de to første implementeringer, er der ingen grund til at kalde file.close(), når du bruger med sætning. Selve med-erklæringen sikrer korrekt anskaffelse og frigivelse af ressourcer. En undtagelse under file.write()-kaldet i den første implementering kan forhindre filen i at lukke korrekt, hvilket kan introducere flere fejl i koden, dvs. mange ændringer i filer træder ikke i kraft før filen er ordentligt lukket. Den anden tilgang i ovenstående eksempel tager sig af alle undtagelserne, men brugen af with-sætningen gør koden kompakt og meget mere læsbar. Med statement hjælper med at undgå fejl og lækager ved at sikre, at en ressource frigives korrekt, når koden, der bruger ressourcen, er fuldstændig eksekveret. With-sætningen bruges populært sammen med filstreams, som vist ovenfor og med låse, sockets, underprocesser og telnets mm.
Understøttelse af with-sætningen i brugerdefinerede objekter
Der er ikke noget særligt i open(), som gør det brugbart med with-sætningen, og den samme funktionalitet kan leveres i brugerdefinerede objekter. Understøttelse med sætning i dine objekter vil sikre, at du aldrig efterlader nogen ressource åben. For at bruge med sætning i brugerdefinerede objekter behøver du kun at tilføje metoderne __enter__() og __exit__() i objektmetoderne. Overvej følgende eksempel for yderligere afklaring.
Python3
lære selen
# 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'>)> |
>
>
Lad os undersøge ovenstående kode. Hvis du bemærker, er det, der følger med nøgleordet, konstruktoren af MessageWriter. Så snart udførelsen kommer ind i konteksten af with-sætningen, oprettes et MessageWriter-objekt, og python kalder derefter __enter__()-metoden. I denne __enter__() metode skal du initialisere den ressource, du ønsker at bruge i objektet. Denne __enter__() metode skal altid returnere en deskriptor af den erhvervede ressource. Hvad er ressourcedeskriptorer? Dette er de håndtag, der leveres af operativsystemet for at få adgang til de anmodede ressourcer. I den følgende kodeblok er filen en beskrivelse af filstrømressourcen.
java strengbygger
Python
file> => open>(>'hello.txt'>)> |
>
>
I MessageWriter-eksemplet ovenfor opretter metoden __enter__() en filbeskrivelse og returnerer den. Navnet xfile her bruges til at henvise til filbeskrivelsen, der returneres af metoden __enter__(). Kodeblokken, der bruger den erhvervede ressource, placeres inde i blokken af with-sætningen. Så snart koden inde i with-blokken udføres, kaldes __exit__() metoden. Alle de erhvervede ressourcer frigives i __exit__() metoden. Sådan bruger vi with-sætningen med brugerdefinerede objekter. Denne grænseflade af __enter__() og __exit__() metoder, som understøtter med sætning i brugerdefinerede objekter, kaldes Context Manager .
Contextlib-modulet
En klassebaseret konteksthåndtering som vist ovenfor er ikke den eneste måde at understøtte with-sætningen i brugerdefinerede objekter. Det kontekstlib modul giver et par flere abstraktioner bygget på den grundlæggende konteksthåndteringsgrænseflade. Her er, hvordan vi kan omskrive konteksthåndteringen for MessageWriter-objektet ved hjælp af contextlib-modulet.
Python3
boble sortere java
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 kodeeksempel på grund af udbytte sætning i sin definition er funktionen open_file() en generator funktion . Når denne open_file()-funktion kaldes, opretter den en ressourcebeskrivelse med navnet fil. Denne ressourcedeskriptor sendes derefter til den, der ringer, og er her repræsenteret af variablen my_file. Efter at koden inde i with-blokken er udført, vender programkontrollen tilbage til funktionen open_file(). Open_file()-funktionen genoptager sin udførelse og udfører koden efter udbyttesætningen. Denne del af koden, der vises efter udbytteerklæringen, frigiver de erhvervede ressourcer. @contextmanageren her er en dekoratør . Den tidligere klassebaserede implementering og denne generatorbaserede implementering af kontekstadministratorer er internt den samme. Mens det senere virker mere læseligt, kræver det kendskab til generatorer, dekoratører og udbytte.