Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

315
Vistas
Invocar un constructor en una declaración 'with'

Tengo el siguiente código:

 class Test: def __init__(self, name): self.name = name def __enter__(self): print(f'entering {self.name}') def __exit__(self, exctype, excinst, exctb) -> bool: print(f'exiting {self.name}') return True with Test('first') as test: print(f'in {test.name}') test = Test('second') with test: print(f'in {test.name}')

Ejecutarlo produce el siguiente resultado:

 entering first exiting first entering second in second exiting second

Pero esperaba que produjera:

 entering first in first exiting first entering second in second exiting second

¿Por qué no se llama el código dentro de mi primer ejemplo?

over 4 years ago · Santiago Trujillo
3 Respuestas
Responde la pregunta

0

El método __enter__ debería devolver el objeto de contexto. with ... as ... usa el valor de retorno de __enter__ para determinar qué objeto darle. Dado que su __enter__ no devuelve nada, implícitamente devuelve None , por lo que test es None .

 with Test('first') as test: print(f'in {test.name}') test = Test('second') with test: print(f'in {test.name}')

Así que test es ninguna. Entonces test.name es un error. Ese error se genera, por lo que se llama a Test('first').__exit__ . __exit__ devuelve True , lo que indica que el error se manejó (esencialmente, que su __exit__ está actuando como un bloque de except ), por lo que el código continúa después del primer bloque with , ya que le dijo a Python que todo estaba bien.

Considerar

 def __enter__(self): print(f'entering {self.name}') return self

También puede considerar no devolver True de __exit__ a menos que realmente tenga la intención de suprimir incondicionalmente todos los errores en el bloque (y comprenda completamente las consecuencias de suprimir los errores de otros programadores, así como KeyboardInterrupt , StopIteration y varias señales del sistema)

over 4 years ago · Santiago Trujillo Denunciar

0

El problema es que su método __enter__ devuelve None . Por lo tanto, a test se le asigna None .

Luego intenta acceder a (None).name , lo que genera un error. Dado que su método __exit__ siempre devuelve True , suprimirá cualquier error. Según los documentos :

Devolver un valor verdadero de este método hará que la declaración with suprima la excepción y continúe la ejecución con la declaración que sigue inmediatamente a la declaración with.

over 4 years ago · Santiago Trujillo Denunciar

0

Creo que este comportamiento se debe a que __enter__ debe devolver algo sobre lo que se operará, que en este caso se accederá con el nombre test . Cambiando __enter__ a lo siguiente

 def __enter__(self): print(f"entering {self.name}") return self

obtenemos el comportamiento esperado.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda