A juzgar por comp.lang.python y otros foros, la nueva sentencia "WITH" de Python 2.5 parece ser un poco confusa, incluso para los programadores experimentados de Python. Como la mayoría de las otras cosas en Python, la declaración with es en realidad muy simple, una vez que entienda el problema que está tratando de resolver. Considere este pedazo de código:
configurar las cosas try: hacer algo finally: liberar las cosas
Aquí, "configurar las cosas" podría ser la apertura de un archivo, o la adquisición de algún tipo de recurso externo, y "liberar las cosas" sería entonces el cierre del archivo, o liberar o eliminar el recurso. La construcción try-finally garantiza que la parte "liberar las cosas" siempre se ejecuta, incluso si el código que realiza el trabajo no termina.
Si haces esto muy seguido, sería muy conveniente si pudieras poner el código "configurar las cosas" y "liberar las cosas" en una función de biblioteca, para que sea fácil de reutilizar. Por supuesto, puedes hacer algo como
def ejecucion_controlada(callback): configurar las cosas try: callback(cosas) finally: liberar las cosas def mi_funcion (cosas): hacer algo ejecucion_controlada(mi_funcion)
Pero eso es demasiado detallado, especialmente si necesita modificar variables locales. Otro enfoque consiste en utilizar un generador de un disparo y utilizar la sentencia for-in para "envolver" el código:
def ejecucion_controlada():
configurar las cosas
try:
yield cosa
finally:
liberar las cosas
for cosa in ejecucion_controlada():
hacer algo with cosa
( Pasa a leer: Los Lenguajes más Amados, Temidos y Deseados del 2017 )
Pero yield ni siquiera se permite dentro de un try-finally en 2.4 y anteriores. Y mientras que podría ser arreglado (y se ha arreglado en 2.5), sigue siendo un poco extraño utilizar una construcción de bucle cuando sabes que sólo desea ejecutar algo una vez.
Así que después de contemplar una serie de alternativas, GvR y el equipo python-dev finalmente desarrollaron una generalización de este último, utilizando un objeto en lugar de un generador para controlar el comportamiento de una pieza externa de código:
class ejecucion_controlada: def __enter__ (self): configurar las cosas return cosa def __exit__ (self, type, value, traceback): liberar las cosas with ejecucion_controlada() as cosa: codigo...
Ahora, cuando se ejecuta la instrucción "with", Python evalúa la expresión, llama al método __enter__ del valor resultante (que se denomina "guardia de contexto") y asigna lo que __enter__ devuelve a la variable dada por as. Python ejecutará entonces el cuerpo del código, y pase lo que pase en ese código, llama al método __exit__ del objeto guardia.
Como bono adicional, el método __exit__ puede ver la excepción, si la hay, y suprimirla o actuar en ella según sea necesario. Para suprimir la excepción, simplemente devuelva un valor verdadero. Por ejemplo, el siguiente método __exit__ traga cualquier TypeError, pero deja todas las demás excepciones a través de:
def __exit__ (self, type, value, traceback): return isinstance(value, TypeError)
( Te puede interesar: Porqué creó Google el lenguaje Go? ¿No era suficiente con Python? )
En Python 2.5, el objeto de archivo se ha equipado con los métodos __enter__ y __exit__ ; el primero simplemente devuelve el objeto del archivo en sí, y el último cierra el archivo:
>>> f = open( "x.txt" ) >>> f <archivo abierto 'x.txt' , modo 'r' en 0x00AE82F0> >>> f.__ enter __() <Archivo abierto 'x.txt' , modo 'r' en 0x00AE82F0> >>> f.read(1) 'X' >>> f.__ exit __(None, None, None) >>> f.read(1) Traceback (most recent call last): File "<stdin>" , linea 1, in <module> ValueError: Operacion de E/S en archivo cerrado
Así que para abrir un archivo, procesar su contenido y cerciorarse de cerrarlo, usted puede hacer simplemente:
with open( "x.txt" ) as f: datos = f.read() hacer algo con datos
¿Y ahora ya entiendes como se usa "WITH"? Déjalo en los comentarios.
gracias, me ayudo a comprender un poco, aclaro soy novato en esto de la programación
ResponderEliminarUna pregunta tomando tu mismo ejemplo
ResponderEliminarwith open( "x.txt" ) as f:
datos = f.read()
Cómo Puedo volver sobre los valores de datos en otro momento del programa. Es decir puedo sacarlos del ciclo with