logo

z instrukcją w Pythonie

W Pythonie z oświadczeniem jest używany w obsłudze wyjątków, aby kod był czystszy i znacznie bardziej czytelny. Upraszcza zarządzanie typowymi zasobami, takimi jak strumienie plików. W poniższym przykładzie kodu zobaczysz, jak użycie instrukcji with sprawia, że ​​kod jest czystszy.

Python3




przycinanie ciągu JavaScript





# 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 !'>)>

>

>

Zauważ, że w przeciwieństwie do dwóch pierwszych implementacji, podczas używania instrukcji with nie ma potrzeby wywoływania metody file.close(). Sama instrukcja with zapewnia prawidłowe pozyskiwanie i uwalnianie zasobów. Wyjątek podczas wywołania file.write() w pierwszej implementacji może uniemożliwić prawidłowe zamknięcie pliku, co może wprowadzić kilka błędów w kodzie, tj. wiele zmian w plikach zaczyna obowiązywać dopiero po prawidłowym zamknięciu pliku. Drugie podejście w powyższym przykładzie uwzględnia wszystkie wyjątki, ale użycie instrukcji with sprawia, że ​​kod jest zwarty i znacznie bardziej czytelny. Zatem instrukcja with pomaga uniknąć błędów i wycieków, zapewniając prawidłowe zwolnienie zasobu po całkowitym wykonaniu kodu korzystającego z zasobu. Instrukcja with jest powszechnie używana w przypadku strumieni plików, jak pokazano powyżej, a także w przypadku blokad, gniazd, podprocesów i telnetów itp.

Obsługa instrukcji with w obiektach zdefiniowanych przez użytkownika

W metodzie open() nie ma nic specjalnego, co sprawiałoby, że można jej używać z instrukcją with, a tę samą funkcjonalność można zapewnić w obiektach zdefiniowanych przez użytkownika. Obsługa instrukcji w obiektach zapewni, że nigdy nie pozostawisz żadnego zasobu otwartego. Aby użyć instrukcji with w obiektach zdefiniowanych przez użytkownika, wystarczy dodać metody __enter__() i __exit__() w metodach obiektowych. Aby uzyskać dalsze wyjaśnienia, rozważ następujący przykład.

Python3

typy komputerów




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

>

string.compareto C#

>

Przeanalizujmy powyższy kod. Jeśli zauważysz, po słowie kluczowym with znajduje się konstruktor MessageWriter. Gdy tylko wykonanie wejdzie w kontekst instrukcji with, tworzony jest obiekt MessageWriter, a następnie Python wywołuje metodę __enter__(). W tej metodzie __enter__() zainicjuj zasób, którego chcesz użyć w obiekcie. Ta metoda __enter__() powinna zawsze zwracać deskryptor pozyskanego zasobu. Co to są deskryptory zasobów? Są to uchwyty udostępniane przez system operacyjny w celu uzyskania dostępu do żądanych zasobów. W poniższym bloku kodu plik jest deskryptorem zasobu strumienia plików.

Pyton




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

>

>

W podanym powyżej przykładzie MessageWriter metoda __enter__() tworzy deskryptor pliku i zwraca go. Nazwa xfile używana jest tutaj w odniesieniu do deskryptora pliku zwracanego przez metodę __enter__(). Blok kodu korzystający z pozyskanego zasobu umieszczony jest wewnątrz bloku instrukcji with. Po wykonaniu kodu znajdującego się w bloku with wywoływana jest metoda __exit__(). Wszystkie pozyskane zasoby zwalniane są w metodzie __exit__(). W ten sposób używamy instrukcji with w przypadku obiektów zdefiniowanych przez użytkownika. Ten interfejs metod __enter__() i __exit__(), który zapewnia obsługę instrukcji with w obiektach zdefiniowanych przez użytkownika, nazywa się Menedżer kontekstu .

Moduł kontekstowy

Menedżer kontekstu oparty na klasach, jak pokazano powyżej, nie jest jedynym sposobem obsługi instrukcji with w obiektach zdefiniowanych przez użytkownika. The biblioteka kontekstowa moduł udostępnia kilka dodatkowych abstrakcji zbudowanych na bazie podstawowego interfejsu menedżera kontekstu. Oto jak możemy przepisać menedżera kontekstu dla obiektu MessageWriter za pomocą modułu kontekstlib.

Python3


pętla foreach maszynopisu



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

>

>

W tym przykładzie kodu, ze względu na dawać instrukcja w swojej definicji, funkcja open_file() to a funkcja generatora . Kiedy wywoływana jest funkcja open_file(), tworzy ona deskryptor zasobu o nazwie plik. Ten deskryptor zasobu jest następnie przekazywany do wywołującego i jest tutaj reprezentowany przez zmienną mój_plik. Po wykonaniu kodu znajdującego się w bloku with sterowanie programem powraca do funkcji open_file(). Funkcja open_file() wznawia wykonywanie i wykonuje kod następujący po instrukcji Yield. Ta część kodu, która pojawia się po instrukcji Yield, zwalnia nabyte zasoby. @contextmanager tutaj to a dekorator . Poprzednia implementacja oparta na klasach i ta oparta na generatorze implementacja menedżerów kontekstu jest wewnętrznie taka sama. O ile ta druga wydaje się bardziej czytelna, wymaga znajomości generatorów, dekoratorów i wydajności.