Em Python, ouço muitas vezes que é melhor "pedir perdão" (captura de exceção) em vez de "pedir permissão" (verificação de tipo / condição). No que diz respeito à imposição de digitação de pato em Python, isso é
try:
x = foo.bar
except AttributeError:
pass
else:
do(x)
melhor ou pior que
if hasattr(foo, "bar"):
do(foo.bar)
else:
pass
em termos de desempenho, legibilidade, "pitônico" ou algum outro fator importante?
exceptions
python
duck-typing
darkfeline
fonte
fonte
hasattr
é implementado com essa tentativa / captura exata internamente. Não certo se é verdade ... (ele agiria de forma diferente sobre as propriedades, não seria Talvez eu estou pensando?getattr
..)hasattr
usa o equivalente C-API degetattr
(retorneTrue
se for bem-sucedido,False
se não), mas lidar com exceções em C é muito mais rápido.Respostas:
Realmente depende de quantas vezes você acha que a exceção será lançada.
Ambas as abordagens são, na minha opinião, igualmente válidas, pelo menos em termos de legibilidade e pitonismo. Mas se 90% dos seus objetos não tiverem o atributo,
bar
você notará uma diferença de desempenho distinta entre as duas abordagens:Mas se 90% dos seus objetos não têm o atributo, as mesas foram viradas:
Portanto, do ponto de vista do desempenho, você precisa escolher a abordagem que melhor funciona para suas circunstâncias.
No final, algum uso estratégico do
timeit
módulo pode ser a coisa mais pitônica que você pode fazer.fonte
hasattr
, na verdade, ele faz o equivalente C-api de uma tentativa, exceto sob o capô de qualquer maneira, uma vez que a única maneira geral de determinar se um objeto tem um atributo no Python é tentar acessá-lo.Em python, você geralmente obtém melhor desempenho fazendo as coisas da maneira Python. Em outros idiomas, o uso de exceções para controle de fluxo é geralmente considerado uma péssima idéia, porque as exceções normalmente impõem uma sobrecarga extraordinária. Mas, como essa técnica é explicitamente recomendada em Python, o intérprete é otimizado para esse tipo de código.
Como em todas as questões de desempenho, a única maneira de ter certeza é criar um perfil do seu código. Escreva as duas versões e veja qual delas roda mais rápido. Embora, na minha experiência, o "caminho Python" seja tipicamente o caminho mais rápido.
fonte
Sinto-me que o desempenho é uma preocupação secundária. Se surgir, um criador de perfil ajudará você a se concentrar nos gargalos reais, que podem ou não ser como você trata possíveis argumentos ilegais.
Legibilidade e simplicidade, por outro lado, são sempre uma preocupação primordial. Não há regras rígidas aqui, apenas use seu julgamento.
Essa é uma questão universal, mas as convenções específicas ao ambiente ou ao idioma são relevantes. Por exemplo, no Python, geralmente é bom simplesmente usar o atributo que você espera e permitir que um possível AttributeError alcance o chamador.
fonte
Em termos de correção , acho que o tratamento de exceções é o caminho a seguir (às vezes uso a abordagem hasattr ()). O problema básico de confiar em hasattr () é que ele transforma violações de contratos de código em falhas silenciosas (esse é um grande problema no JavaScript, que não gera propriedades não existentes).
fonte