Estou trabalhando em um pequeno projeto de hobby usando Python. Quero "fazer direito" e seguir diretrizes comuns.
Seguindo um pacote de exemplo usando SQLite, posso fazer as coisas funcionarem bem usando contexto.
Exemplo:
import mypackage as mp
with mp.democlass() as dc:
dc.dosomething('some_parameter')
Isso obviamente chama as funções __enter__
e __exit__
.
Se eu desejar empacotar meu trabalho para que ele também possa ser usado sem a with
função, por exemplo:
dc = mp.democlass()
dc.dosomething('some_parameter')
.. qual seria a abordagem "correta". Posso determinar na classe se ela é usada em with
contexto, ou preciso codificar uma função de inicialização idêntica a __enter__
, por exemplo, para abrir uma conexão de banco de dados.
Espero que a pergunta faça sentido. Talvez eu precise de um módulo boilerplate que tenha ambas as maneiras.
Existem algumas classes, mesmo na biblioteca padrão do Python, que podem usar um contexto apenas como uma opção. (Por exemplo,
concurrent.futures
executores, ou mesmo o objeto retornado por uma chamada de arquivo internaopen
)O padrão geral é que todos os recursos necessários são criados diretamente no
__init__
método, e o__enter__
método se torna essencialmente uma "operação nula", com seu corpo sendo, geralmente, uma únicareturn self
linha.Nesses casos, qualquer limpeza de recurso que precise ser realizada (por exemplo, confirmar uma transação) pode ser feita em um método público (que pode ser nomeado
close
oucommit
) - e o__exit__
método chamará esse método de seu corpo. O__del__
método na classe será chamado, de forma determinística, se o objeto for simplesmente desreferenciado em um "caminho feliz" - mas ele nunca poderia ser executado em casos extremos, como quando uma exceção ocorre e o interpretador sai. Toda a documentação (e minha própria experiência ao vivo) é unânime em desaconselhar a adição de ações de limpeza importantes apenas como parte de um__del__
método (aliás, exceções levantadas dentro de um__del__
método são engolidas e nem mesmo impressas)Dessa forma, as pessoas ficam livres para usar o recurso fora de um
with
bloco do gerenciador de contexto, mas, ao fazer isso, assumem a responsabilidade de garantir que o método de limpeza seja chamado.