Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

178
Visualizações
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 Respostas
Responde à pergunta

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 Relatório

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 Relatório

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda