În Python, cu declarație este folosit în gestionarea excepțiilor pentru a face codul mai curat și mult mai lizibil. Simplifică gestionarea resurselor comune, cum ar fi fluxurile de fișiere. Observați următorul exemplu de cod despre modul în care utilizarea declarației with face codul mai curat.
Python3
conține metoda 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 !'>)> |
>
state din SUA
>
Observați că, spre deosebire de primele două implementări, nu este nevoie să apelați file.close() când utilizați instrucțiunea with. Declarația with în sine asigură achiziția și eliberarea adecvată a resurselor. O excepție în timpul apelului file.write() în prima implementare poate împiedica închiderea corectă a fișierului, ceea ce poate introduce mai multe erori în cod, adică multe modificări ale fișierelor nu intră în vigoare până când fișierul este închis corespunzător. A doua abordare din exemplul de mai sus are grijă de toate excepțiile, dar utilizarea instrucțiunii with face codul compact și mult mai ușor de citit. Astfel, cu declarația ajută la evitarea erorilor și scurgerilor, asigurându-se că o resursă este eliberată corect atunci când codul care utilizează resursa este complet executat. Declarația with este folosită în mod obișnuit cu fluxurile de fișiere, așa cum se arată mai sus și cu Blocări, socket-uri, subprocese și telnet-uri etc.
Sprijinirea instrucțiunii with în obiectele definite de utilizator
Nu există nimic special în open() care îl face utilizabil cu instrucțiunea with și aceeași funcționalitate poate fi furnizată în obiectele definite de utilizator. Sprijinirea cu declarații în obiectele dvs. vă va asigura că nu lăsați niciodată nicio resursă deschisă. Pentru a utiliza instrucțiunea cu în obiectele definite de utilizator, trebuie doar să adăugați metodele __enter__() și __exit__() în metodele obiect. Luați în considerare următorul exemplu pentru o clarificare suplimentară.
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'>)> |
>
ubuntu build essentials
>
Să examinăm codul de mai sus. Dacă observați, ceea ce urmează cuvântul cheie with este constructorul MessageWriter. De îndată ce execuția intră în contextul instrucțiunii with, este creat un obiect MessageWriter și apoi python apelează metoda __enter__(). În această metodă __enter__(), inițializați resursa pe care doriți să o utilizați în obiect. Această metodă __enter__() ar trebui să returneze întotdeauna un descriptor al resursei achiziționate. Ce sunt descriptorii de resurse? Acestea sunt mânerele furnizate de sistemul de operare pentru a accesa resursele solicitate. În următorul bloc de cod, fișierul este un descriptor al resursei fluxului de fișiere.
Piton
file> => open>(>'hello.txt'>)> |
>
>
În exemplul MessageWriter furnizat mai sus, metoda __enter__() creează un descriptor de fișier și îl returnează. Numele xfile aici este folosit pentru a se referi la descriptorul de fișier returnat de metoda __enter__(). Blocul de cod care folosește resursa achiziționată este plasat în blocul instrucțiunii with. De îndată ce codul din interiorul blocului with este executat, este apelată metoda __exit__(). Toate resursele dobândite sunt eliberate în metoda __exit__(). Acesta este modul în care folosim instrucțiunea with cu obiecte definite de utilizator. Această interfață a metodelor __enter__() și __exit__() care oferă suport pentru instrucțiunea with în obiectele definite de utilizator se numește Manager de context .
qiuck sort
Modulul contextlib
Un manager de context bazat pe clasă, așa cum se arată mai sus, nu este singura modalitate de a sprijini instrucțiunea with în obiectele definite de utilizator. The contextlib modulul oferă mai multe abstracții construite pe interfața de bază a managerului de context. Iată cum putem rescrie managerul de context pentru obiectul MessageWriter folosind modulul contextlib.
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'>)> |
>
>
În acest exemplu de cod, din cauza Randament declarație în definiția sa, funcția open_file() este a funcția de generator . Când această funcție open_file() este apelată, creează un descriptor de resurse numit fișier. Acest descriptor de resursă este apoi transmis apelantului și este reprezentat aici de variabila my_file. După ce codul din blocul with este executat, controlul programului revine la funcția open_file(). Funcția open_file() își reia execuția și execută codul după instrucțiunea yield. Această parte a codului care apare după declarația de randament eliberează resursele achiziționate. @contextmanager aici este un decorator . Implementarea anterioară bazată pe clasă și această implementare bazată pe generator a managerilor de context este la nivel intern aceeași. În timp ce mai târziu pare mai lizibil, necesită cunoștințele generatorilor, decoratorilor și randamentului.