En Python, amb declaració s'utilitza en el maneig d'excepcions per fer que el codi sigui més net i molt més llegible. Simplifica la gestió de recursos comuns com els fluxos de fitxers. Observeu l'exemple de codi següent sobre com l'ús de la sentència with fa que el codi sigui més net.
Python 3
hashmap
# 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()> |
>
>
Python 3
# using with statement> with>open>(>'file_path'>,>'w'>) as>file>:> >file>.write(>'hello world !'>)> |
botó per centrar css
>
>
Tingueu en compte que, a diferència de les dues primeres implementacions, no cal cridar a file.close() quan s'utilitza amb la instrucció. La declaració amb en si garanteix l'adquisició i l'alliberament adequats dels recursos. Una excepció durant la crida a file.write() a la primera implementació pot evitar que el fitxer es tanqui correctament, cosa que pot introduir diversos errors al codi, és a dir, molts canvis als fitxers no entren en vigor fins que el fitxer no es tanca correctament. El segon enfocament de l'exemple anterior té cura de totes les excepcions, però l'ús de la instrucció with fa que el codi sigui compacte i molt més llegible. Així, amb declaració ajuda a evitar errors i filtracions assegurant-se que un recurs s'allibera correctament quan el codi que utilitza el recurs s'executa completament. La declaració with s'utilitza popularment amb fluxos de fitxers, com es mostra a dalt i amb bloquejos, sòcols, subprocessos i telnets, etc.
Admet la instrucció with en objectes definits per l'usuari
No hi ha res especial a l'open() que el faci utilitzable amb la instrucció with i la mateixa funcionalitat es pot proporcionar als objectes definits per l'usuari. Donar suport amb declaració als vostres objectes us garantirà que mai deixeu cap recurs obert. Per utilitzar la instrucció amb en objectes definits per l'usuari només cal afegir els mètodes __enter__() i __exit__() als mètodes d'objecte. Considereu l'exemple següent per a més aclariments.
Python 3
Madhubala
# 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'>)> |
>
>
Examinem el codi anterior. Si ho observeu, el que segueix la paraula clau with és el constructor de MessageWriter. Tan bon punt l'execució entra al context de la instrucció with es crea un objecte MessageWriter i Python crida al mètode __enter__(). En aquest mètode __enter__(), inicialitzeu el recurs que voleu utilitzar a l'objecte. Aquest mètode __enter__() sempre hauria de retornar un descriptor del recurs adquirit. Què són els descriptors de recursos? Aquests són els identificadors que proporciona el sistema operatiu per accedir als recursos sol·licitats. Al bloc de codi següent, el fitxer és un descriptor del recurs del flux de fitxers.
Python
file> => open>(>'hello.txt'>)> |
>
com injectar una classe abstracta simulada
>
A l'exemple de MessageWriter proporcionat anteriorment, el mètode __enter__() crea un descriptor de fitxer i el retorna. El nom xfile aquí s'utilitza per referir-se al descriptor de fitxer retornat pel mètode __enter__(). El bloc de codi que utilitza el recurs adquirit es col·loca dins del bloc de la instrucció with. Tan bon punt s'executa el codi dins del bloc with, es crida al mètode __exit__(). Tots els recursos adquirits s'alliberen amb el mètode __exit__(). Així és com fem servir la instrucció with amb objectes definits per l'usuari. Aquesta interfície dels mètodes __enter__() i __exit__() que proporciona el suport de la instrucció with en objectes definits per l'usuari s'anomena Gestor de context .
El mòdul contextlib
Un gestor de context basat en classes, com es mostra més amunt, no és l'única manera de donar suport a la instrucció with als objectes definits per l'usuari. El contextlib El mòdul proporciona algunes abstraccions més basades en la interfície bàsica del gestor de context. A continuació s'explica com podem reescriure el gestor de context per a l'objecte MessageWriter mitjançant el mòdul contextlib.
Python 3
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'>)> |
>
>
En aquest exemple de codi, a causa del rendiment declaració a la seva definició, la funció open_file() és a funció de generador . Quan es crida aquesta funció open_file(), crea un descriptor de recursos anomenat fitxer. Aquest descriptor de recurs es passa a la persona que truca i aquí es representa amb la variable my_file. Després d'executar el codi dins del bloc with, el control del programa torna a la funció open_file(). La funció open_file() reprèn la seva execució i executa el codi seguint la instrucció yield. Aquesta part del codi que apareix després de la declaració de rendiment allibera els recursos adquirits. El @contextmanager aquí és un decorador . La implementació anterior basada en classes i aquesta implementació basada en generadors de gestors de context és internament la mateixa. Tot i que això posterior sembla més llegible, requereix el coneixement de generadors, decoradors i rendiment.