En Python, a menudo escucho que es mejor "pedir perdón" (captura de excepción) en lugar de "pedir permiso" (verificación de tipo / condición). En lo que respecta a hacer cumplir la escritura de pato en Python, ¿es esto
try:
x = foo.bar
except AttributeError:
pass
else:
do(x)
mejor o peor que
if hasattr(foo, "bar"):
do(foo.bar)
else:
pass
en términos de rendimiento, legibilidad, "pitónico" o algún otro factor importante?
exceptions
python
duck-typing
darkfeline
fuente
fuente
hasattr
se implementa con ese intento / captura exacto internamente. No estoy seguro de si es verdad ... (actuaría de manera diferente en las propiedades, ¿no? Tal vez estoy pensando engetattr
...)hasattr
utiliza el equivalente C-API degetattr
(devolverTrue
si tiene éxito,False
si no), pero manejar excepciones en C es mucho más rápido.Respuestas:
Realmente depende de la frecuencia con la que piense que se lanzará la excepción.
Ambos enfoques son, en mi opinión, igualmente válidos, al menos en términos de legibilidad y pitonismo. Pero si el 90% de sus objetos no tienen el atributo
bar
, notará una diferencia de rendimiento distinta entre los dos enfoques:Pero si el 90% de los objetos no tienen el atributo, las tablas se han convertido:
Entonces, desde el punto de vista del rendimiento, debe elegir el enfoque que mejor se adapte a sus circunstancias.
Al final, un uso estratégico del
timeit
módulo puede ser lo más Pythonic que puede hacer.fuente
hasattr
, de todos modos, en realidad hace el equivalente C-api de un try, excepto bajo el capó, ya que resulta que la única forma general de determinar si un objeto tiene un atributo en Python es intentar acceder a él.En Python, a menudo obtienes un mejor rendimiento haciendo las cosas al estilo Python. Con otros lenguajes, el uso de excepciones para el control de flujo generalmente se considera una idea terrible porque las excepciones suelen imponer una sobrecarga extraordinaria. Pero debido a que esta técnica está explícitamente respaldada en Python, el intérprete está optimizado para este tipo de código.
Como con todas las preguntas de rendimiento, la única forma de estar seguro es perfilar su código. Escriba ambas versiones y vea cuál funciona más rápido. Aunque en mi experiencia, la "forma de Python" suele ser la forma más rápida.
fuente
El rendimiento, creo, es una preocupación secundaria. Si surge, un generador de perfiles lo ayudará a centrarse en los cuellos de botella reales, que pueden ser o no la forma en que trata los posibles argumentos ilegales.
La legibilidad y la simplicidad, por otro lado, son siempre una preocupación principal. Aquí no hay reglas estrictas, solo usa tu criterio.
Este es un problema universal, pero las convenciones específicas del entorno o del lenguaje son relevantes. Por ejemplo, en Python generalmente está bien simplemente usar el atributo que espera y dejar que un posible AttributeError llegue a la persona que llama.
fuente
En términos de corrección , creo que el manejo de excepciones es el camino a seguir (aunque a veces uso el enfoque hasattr ()). El problema básico con confiar en hasattr () es que convierte las violaciones de los contratos de código en fallas silenciosas (este es un gran problema en JavaScript, que no arroja propiedades no existentes).
fuente