I Python, med uttalande används i undantagshantering för att göra koden renare och mycket mer läsbar. Det förenklar hanteringen av vanliga resurser som filströmmar. Observera följande kodexempel om hur användningen av with statement gör koden renare.
Python3
konvertera sträng till jsonobject java
# 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 !'>)> |
>
>
primär nyckel sammansatt nyckel
Observera att till skillnad från de två första implementeringarna, finns det inget behov av att anropa file.close() när du använder med satsen. Med uttalandet i sig säkerställer korrekt förvärv och frigörande av resurser. Ett undantag under file.write()-anropet i den första implementeringen kan förhindra att filen stängs ordentligt vilket kan introducera flera buggar i koden, det vill säga många ändringar i filer träder inte i kraft förrän filen stängs ordentligt. Den andra metoden i exemplet ovan tar hand om alla undantag, men att använda with-satsen gör koden kompakt och mycket mer läsbar. Med statement hjälper alltså till att undvika buggar och läckor genom att se till att en resurs släpps korrekt när koden som använder resursen är helt exekverad. With-satsen används populärt med filströmmar, som visas ovan och med lås, sockets, underprocesser och telnets etc.
Stödja with-satsen i användardefinierade objekt
Det finns inget speciellt i open() som gör den användbar med with-satsen och samma funktionalitet kan tillhandahållas i användardefinierade objekt. Att stödja med statement i dina objekt kommer att säkerställa att du aldrig lämnar någon resurs öppen. För att använda med sats i användardefinierade objekt behöver du bara lägga till metoderna __enter__() och __exit__() i objektmetoderna. Betrakta följande exempel för ytterligare förtydligande.
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'>)> |
>
>
Låt oss undersöka ovanstående kod. Om du märker, vad som följer med nyckelordet med är konstruktören av MessageWriter. Så fort exekveringen går in i kontexten för with-satsen skapas ett MessageWriter-objekt och python anropar sedan metoden __enter__(). I den här metoden __enter__() initialiserar du resursen du vill använda i objektet. Den här metoden __enter__() ska alltid returnera en deskriptor för den förvärvade resursen. Vad är resursdeskriptorer? Dessa är handtagen som tillhandahålls av operativsystemet för att komma åt de begärda resurserna. I följande kodblock är filen en beskrivning av filströmsresursen.
Pytonorm
sökväg satt i java
file> => open>(>'hello.txt'>)> |
>
>
I MessageWriter-exemplet ovan skapar metoden __enter__() en filbeskrivning och returnerar den. Namnet xfile här används för att referera till filbeskrivningen som returneras av metoden __enter__(). Kodblocket som använder den förvärvade resursen placeras inuti blocket av with-satsen. Så snart koden inuti with-blocket exekveras, anropas metoden __exit__(). Alla förvärvade resurser släpps i metoden __exit__() . Så här använder vi with-satsen med användardefinierade objekt. Detta gränssnitt av metoderna __enter__() och __exit__() som ger stöd för med sats i användardefinierade objekt kallas Kontexthanterare .
Contextlib-modulen
En klassbaserad kontexthanterare som visas ovan är inte det enda sättet att stödja with-satsen i användardefinierade objekt. De contextlib modulen ger några fler abstraktioner byggda på det grundläggande kontexthanterarens gränssnitt. Så här kan vi skriva om kontexthanteraren för MessageWriter-objektet med hjälp av modulen contextlib.
git-kommandon för push
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 detta kodexempel, på grund av avkastning i dess definition är funktionen open_file() en generatorfunktion . När den här open_file()-funktionen anropas skapar den en resursdeskriptor med namnet fil. Denna resursbeskrivning skickas sedan till anroparen och representeras här av variabeln my_file. Efter att koden inuti with-blocket har körts återgår programkontrollen till funktionen open_file(). Open_file()-funktionen återupptar sin exekvering och exekverar koden efter yield-satsen. Denna del av koden som visas efter att avkastningssatsen släpper de förvärvade resurserna. @contextmanager här är en dekoratör . Den tidigare klassbaserade implementeringen och denna generatorbaserade implementering av kontexthanterare är internt densamma. Även om det senare verkar mer läsbart, kräver det kunskap om generatorer, dekoratörer och avkastning.