Widziałem to w czyimś kodzie. Co to znaczy?
def __enter__(self):
return self
def __exit__(self, type, value, tb):
self.stream.close()
from __future__ import with_statement#for python2.5
class a(object):
def __enter__(self):
print 'sss'
return 'sss111'
def __exit__(self ,type, value, traceback):
print 'ok'
return False
with a() as s:
print s
print s
python
oop
with-statement
zjm1126
źródło
źródło
Odpowiedzi:
Korzystanie z tych magicznych metod (
__enter__
,__exit__
) pozwala na implementację obiektów, których można łatwo używać zwith
instrukcją.Chodzi o to, że ułatwia budowanie kodu, który wymaga wykonania kodu „wyczyszczenia” (traktuj go jako
try-finally
blok). Więcej wyjaśnień tutaj .Przydatnym przykładem może być obiekt połączenia z bazą danych (który następnie automatycznie zamyka połączenie, gdy odpowiednia instrukcja „z” wykracza poza zakres):
Jak wyjaśniono powyżej, użyj tego obiektu z
with
instrukcją (możesz potrzebować zrobić tofrom __future__ import with_statement
na górze pliku, jeśli korzystasz z Python 2.5).PEP343 - Polecenie „z” ma również niezły opis.
źródło
__enter__
powinienself
zawsze zwracać, ponieważ w kontekście można wywoływać tylko inne metody klasy.def __enter__(self)
PEP 343 i nikt tego nie robireturn self
: python.org/dev/peps/pep-0343 . Dlaczego tak myślisz?self
obiekcie, jak wyjaśniono tutaj: stackoverflow.com/questions/38281853/... 2) self.XYZ jest tylko częścią self obiektu i zwracanie uchwytu tylko do tego, co wydaje mi się nieodpowiednie z punktu widzenia konserwacji. Wolałbym wolą wrócić do pełnej uchwyt obiektu, a następnie dostarczyć API publiczne tylko te elementyself
obiektu, który chcę wystawiać użytkownikowi jak wwith open(abc.txt, 'r') as fin: content = fin.read()
self
z__enter__
tego powodu możesz przetwarzać plik jak wf
środkuwith open(...) as f
Jeśli wiesz, kim są menedżerowie kontekstu, nie potrzebujesz nic więcej do zrozumienia
__enter__
i__exit__
magicznych metod. Zobaczmy bardzo prosty przykład.W tym przykładzie otwieram plik myfile.txt za pomocą funkcji open . Blok try / wreszcie zapewnia, że nawet jeśli wystąpi nieoczekiwany wyjątek, plik myfile.txt zostanie zamknięty.
Teraz otwieram ten sam plik z instrukcją:
Jeśli spojrzysz na kod, nie zamknąłem pliku i nie ma bloku try / wreszcie . Ponieważ z instrukcją automatycznie zamyka plik myfile.txt . Możesz to nawet sprawdzić, wywołując
print(fp.closed)
atrybut - który zwracaTrue
.Jest tak, ponieważ obiekty plików (fp w moim przykładzie) zwrócone przez funkcję open mają dwie wbudowane metody
__enter__
i__exit__
. Jest również znany jako menedżer kontekstu.__enter__
Metoda jest wywoływana na początku za pomocą bloku, a__exit__
metoda jest wywoływana na końcu. Uwaga: z instrukcją działa tylko z obiektami, które obsługują protokół modyfikowania kontekstu, tj. Mają__enter__
i__exit__
metody. Klasa implementująca obie metody jest znana jako klasa menedżera kontekstu.Teraz pozwala zdefiniować naszą własną klasę menedżera kontekstu .
Mam nadzieję, że teraz rozumiesz obie metody
__enter__
i__exit__
metody magiczne.źródło
Znalezienie dokumentacji
__enter__
i__exit__
metod Pythona przez Googlinga było dla mnie dziwnie trudne , więc aby pomóc innym tutaj, jest link:https://docs.python.org/2/reference/datamodel.html#with-statement-context-managers
https://docs.python.org/3/reference/datamodel.html#with-statement-context-managers
(szczegóły są takie same dla obu wersji)
Miałem nadzieję na jasny opis
__exit__
argumentów metody. Tego brakuje, ale możemy je wywnioskować ...Prawdopodobnie
exc_type
jest to klasa wyjątku.Mówi, że nie powinieneś ponownie podnosić przekazywanego wyjątku. Sugeruje to nam, że jednym z argumentów może być faktyczna instancja wyjątku ... a może powinieneś utworzyć ją samodzielnie z rodzaju i wartości?
Możemy odpowiedzieć, patrząc na ten artykuł:
http://effbot.org/zone/python-with-statement.htm
... tak wyraźnie
value
jest przypadek wyjątku.I prawdopodobnie
traceback
jest to obiekt śledzenia w Pythonie .źródło
Oprócz powyższych odpowiedzi w celu zilustrowania kolejności wywoływania, prosty przykład uruchomienia
Daje wynik:
Przypomnienie: podczas korzystania ze składni
with myclass() as mc
zmienna mc otrzymuje wartość zwracaną przez__enter__()
, w powyższym przypadkuNone
! W takim przypadku należy zdefiniować wartość zwracaną, na przykład:źródło
spróbuj dodać moje odpowiedzi (moja myśl o nauce):
__enter__
i[__exit__]
obie są metodami wywoływanymi przy wejściu i wyjściu z treści „ instrukcji with ” ( PEP 343 ), a implementacja obu nazywa się menedżerem kontekstu.instrukcja with ma na celu ukrycie kontroli przepływu klauzuli try last i uczynienie kodu nieodgadnialnym.
składnia instrukcji with jest następująca:
co przekłada się na (jak wspomniano w PEP 343):
spróbuj trochę kodu:
i teraz spróbuj ręcznie (zgodnie ze składnią tłumaczenia):
wynik po stronie serwera taki sam jak poprzednio
przepraszam za mój zły angielski i niejasne wyjaśnienia, dziękuję ....
źródło
Nazywa się to menedżerem kontekstu i chcę tylko dodać, że podobne podejścia istnieją w przypadku innych języków programowania. Porównanie ich może być pomocne w zrozumieniu menedżera kontekstu w Pythonie. Zasadniczo menedżer kontekstu jest używany, gdy mamy do czynienia z niektórymi zasobami (plik, sieć, baza danych), które muszą zostać zainicjowane, aw pewnym momencie zerwane (usunięte). W Javie 7 i nowszych mamy automatyczne zarządzanie zasobami, które przyjmuje postać:
Należy pamiętać, że Sesja musi zostać wdrożona
AutoClosable
lub jeden z (wielu) pod-interfejsów.W języku C # używamy instrukcji do zarządzania zasobami, które mają postać:
W którym
Session
należy wdrożyćIDisposable
.W Pythonie klasa, której używamy, powinna implementować
__enter__
i__exit__
. Przybiera więc postać:I jak zauważyli inni, zawsze możesz użyć instrukcji try / wreszcie we wszystkich językach, aby zaimplementować ten sam mechanizm. To tylko cukier syntaktyczny.
źródło