O motivo pelo qual você deve usar a primeira versão é o desempenho. Aumentar uma exceção geralmente é mais barato do que chamar um método ou uma função.
O primeiro argumento que você apresenta para usar a segunda versão não é válido, já que usar if hasattr(duck, 'quack'):
também evitaria a chamada silenciosa para duck.quack()
e nenhuma exceção seria levantada.
Seu segundo argumento só se aplica porque sua implementação não está correta. Você deve fazê-lo da seguinte forma:
def quackAllDucks(ducks):
for duck in ducks:
try:
duck.quack
except AttributeError:
#Not a duck, can't quack, don't worry about it
continue
duck.quack("QUACK")
Então qualquer exceção levantada dentro de duck.quack()
seria propagada para o chamador de quackAllDucks()
.
[EDITAR]
delnan levantou uma boa pergunta em seu comentário abaixo. Isso me levou a investigar mais, e a forma recomendada agora parece ser para usar hasattr()
.
Mas a melhor solução é provavelmente projetar seu programa para que ele não dependa de tais testes. Como Steve Oualline disse: " Se não escrevermos código como este, então não precisamos nos preocupar tais perguntas " .