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

178
Vistas
Invoking a constructor in a 'with' statement

I have the following code:

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}')

Running it produces the following output:

entering first
exiting first
entering second
in second
exiting second

But I expected it to produce:

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

Why isn't the code within my first example called?

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

0

The __enter__ method should return the context object. with ... as ... uses the return value of __enter__ to determine what object to give you. Since your __enter__ returns nothing, it implicitly returns None, so test is None.

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

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

So test is none. Then test.name is an error. That error gets raised, so Test('first').__exit__ gets called. __exit__ returns True, which indicates that the error has been handled (essentially, that your __exit__ is acting like an except block), so the code continues after the first with block, since you told Python everything was fine.

Consider

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

You might also consider not returning True from __exit__ unless you truly intend to unconditionally suppress all errors in the block (and fully understand the consequences of suppressing other programmers' errors, as well as KeyboardInterrupt, StopIteration, and various system signals)

over 4 years ago · Santiago Trujillo Denunciar

0

The problem is that your __enter__ method returns None. Hence, test is assigned None.

Then you try to access (None).name, which raises an error. Since your __exit__ method returns True always, it will suppress any errors. According to the docs:

Returning a true value from this method will cause the with statement to suppress the exception and continue execution with the statement immediately following the with statement.

over 4 years ago · Santiago Trujillo Denunciar

0

I believe this behavior is because __enter__ must return something that will be operated on, that in this case will be accessed with the name test. By changing __enter__ to the following

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

we get the expected behavior.

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