tutorial examples espaƱol ejemplos python oop with-statement

examples - Explicando ''__enter__'' y ''__exit__'' de Python



plot python 3 (4)

Vi esto en el código de alguien. Qué significa eso?

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


Además de las respuestas anteriores para ejemplificar el orden de invocación, un ejemplo de ejecución simple

class myclass: def __init__(self): print("__init__") def __enter__(self): print("__enter__") def __exit__(self, type, value, traceback): print("__exit__") def __del__(self): print("__del__") with myclass(): print("body")

Produce la salida:

__init__ __enter__ body __exit__ __del__

Un recordatorio: cuando se utiliza la sintaxis with myclass() as mc , la variable mc obtiene el valor devuelto por __enter__() , en el caso anterior ¡ None ! Para tal uso, es necesario definir el valor de retorno, como:

def __enter__(self): print(''__enter__'') return self


El uso de estos métodos mágicos ( __enter__ , __exit__ ) le permite implementar objetos que se pueden usar fácilmente con la instrucción with .

La idea es que facilita la creación de código que necesita un código de ''limpieza'' ejecutado (considérelo como un bloque try-finally ). effbot.org/zone/python-with-statement.htm .

Un ejemplo útil podría ser un objeto de conexión de base de datos (que luego cierra automáticamente la conexión una vez que la declaración ''with'' correspondiente se sale del alcance):

class DatabaseConnection(object): def __enter__(self): # make a database connection and return it ... return self.dbconn def __exit__(self, exc_type, exc_val, exc_tb): # make sure the dbconnection gets closed self.dbconn.close() ...

Como se explicó anteriormente, use este objeto con la instrucción with (es posible que tenga que hacerlo from __future__ import with_statement en la parte superior del archivo si está en Python 2.5).

with DatabaseConnection() as mydbconn: # do stuff

PEP343 - El ''con'' declaración ''también tiene una buena reseña.


Me resultó extrañamente difícil localizar los documentos de Python para los métodos __enter__ y __exit__ de Google, así que para ayudar a otros aquí está el enlace:

https://docs.python.org/2/reference/datamodel.html#with-statement-context-managers

object.__enter__(self)
Ingrese el contexto de tiempo de ejecución relacionado con este objeto. La declaración with vinculará el valor de retorno de este método al objetivo (s) especificado en la cláusula as de la declaración, si la hubiera.

object.__exit__(self, exc_type, exc_value, traceback)
Salga del contexto de tiempo de ejecución relacionado con este objeto. Los parámetros describen la excepción que causó que se salga el contexto. Si se salió del contexto sin una excepción, los tres argumentos serán None .

Si se proporciona una excepción, y el método desea suprimir la excepción (es decir, evitar que se propague), debe devolver un valor verdadero. De lo contrario, la excepción se procesará normalmente al salir de este método.

Tenga en cuenta que los __exit__() no deben __exit__() excepción pasada; esta es la responsabilidad del que llama.

Esperaba una descripción clara de los argumentos del método __exit__ . Esto falta pero podemos deducirlos ...

Presumiblemente, exc_type es la clase de la excepción.

Dice que no debe volver a elevar la excepción pasada. Esto nos sugiere que uno de los argumentos podría ser una instancia de Excepción real ... ¿o quizás se supone que debe crear una instancia del mismo tipo y valor?

Podemos responder mirando este artículo:
effbot.org/zone/python-with-statement.htm

Por ejemplo, el siguiente método __exit__ traga cualquier TypeError, pero permite todas las demás excepciones a través de:

def __exit__(self, type, value, traceback): return isinstance(value, TypeError)

... tan claramente el value es una instancia de excepción.

Y presumiblemente, el traceback es un objeto de traceback Python.


Si sabe qué son los gestores de contexto, entonces no necesita nada más para entender los métodos mágicos __enter__ y __exit__ . Veamos un ejemplo muy simple.

En este ejemplo, estoy abriendo myfile.txt con la ayuda de la función de apertura . El bloque try / finally garantiza que incluso si ocurre una excepción inesperada, myfile.txt se cerrará.

fp=open(r"C:/Users/SharpEl/Desktop/myfile.txt") try: for line in fp: print(line) finally: fp.close()

Ahora estoy abriendo el mismo archivo con la declaración:

with open(r"C:/Users/SharpEl/Desktop/myfile.txt") as fp: for line in fp: print(line)

Si observa el código, no cerré el archivo y no hay un bloque try / finally . Porque con la sentencia se cierra automáticamente myfile.txt . Incluso puede verificarlo llamando al atributo print(fp.closed) , que devuelve True .

Esto se debe a que los objetos de archivo (fp en mi ejemplo) devueltos por la función open tienen dos métodos __enter__ y __exit__ . También se conoce como gestor de contexto. __enter__ método __enter__ se llama al principio con bloque y el método __exit__ se llama al final. Nota: con la declaración solo funciona con objetos que admiten el protocolo de cambio de contexto, es decir, tienen los métodos __enter__ y __exit__ . Una clase que implementa ambos métodos se conoce como clase de administrador de contexto.

Ahora vamos a definir nuestra propia clase de administrador de contexto .

class Log: def __init__(self,filename): self.filename=filename self.fp=None def logging(self,text): self.fp.write(text+''/n'') def __enter__(self): print("__enter__") self.fp=open(self.filename,"a+") return self def __exit__(self, exc_type, exc_val, exc_tb): print("__exit__") self.fp.close() with Log(r"C:/Users/SharpEl/Desktop/myfile.txt") as logfile: print("Main") logfile.logging("Test1") logfile.logging("Test2")

Espero que ahora tengas un entendimiento básico de los métodos mágicos __enter__ y __exit__ .