• Jobs
  • About Us
  • professionals
    • Home
    • Jobs
    • Courses and challenges
  • business
    • Home
    • Post vacancy
    • Our process
    • Pricing
    • Assessments
    • Payroll
    • Blog
    • Sales
    • Salary Calculator

0

264
Views
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?

about 3 years ago · Santiago Trujillo
3 answers
Answer question

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)

about 3 years ago · Santiago Trujillo Report

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.

about 3 years ago · Santiago Trujillo Report

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.

about 3 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Our process Sales
Legal
Terms and conditions Privacy policy
© 2025 PeakU Inc. All Rights Reserved.

Andres GPT

Recommend me some offers
I have an error