python isinstance vs hasattr vs try / except: ¿Qué es mejor?

Estoy tratando de averiguar las compensaciones entre diferentes enfoques para determinar si con el objeto obj puede o no realizar la acción do_stuff() . Según tengo entendido, hay tres formas de determinar si esto es posible:

 # Way 1 if isinstance(obj, Foo): obj.do_stuff() # Way 2 if hasattr(obj, 'do_stuff'): obj.do_stuff() # Way 3 try: obj.do_stuff() except: print 'Do something else' 

¿Cuál es el método preferido (y por qué)?

Creo que los codificadores de Python prefieren generalmente el último método debido a un lema que se enseña en la comunidad de Python: “Más fácil pedir perdón que permiso” (EAFP).

En pocas palabras, el lema significa evitar comprobar si puedes hacer algo antes de hacerlo. En su lugar, simplemente ejecute la operación. Si falla, manéjalo apropiadamente.

Además, el tercer método tiene la ventaja adicional de dejar en claro que la operación debería funcionar.


Con eso dicho, deberías evitar el uso de un desnudo, except así. Si lo hace, capturará cualquier excepción, incluso las no relacionadas. En su lugar, es mejor capturar excepciones específicamente.

Aquí, usted querrá capturar para un AttributeError :

 try: obj.do_stuff() # Try to invoke do_stuff except AttributeError: print 'Do something else' # If unsuccessful, do something else 

La verificación con isinstance es contraria a la convención de Python de usar la escritura de pato .

hasattr funciona bien, pero es Mirar antes de hasattr , en lugar de más EAFP de Pythonic.

Su implementación de la forma 3 es peligrosa, ya que do_stuff todos los errores, incluidos los provocados por el método do_stuff . Podrías ir con el más preciso:

 try: _ds = obj.do_stuff except AttributeError: print('Do something else') else: _ds() 

Pero en este caso, preferiría el modo 2 a pesar de la ligera sobrecarga, es más fácil de leer.

La respuesta correcta es ‘ninguno’ hasattr ofrece funcionalidad, sin embargo, es posiblemente la peor de todas las opciones.

Usamos la naturaleza orientada a objetos de python porque funciona. El análisis de OO nunca es preciso y, a menudo, confunde, sin embargo, usamos jerarquías de clase porque sabemos que ayudan a las personas a trabajar mejor más rápido. Las personas aferran objetos y un buen modelo de objetos ayuda a los progtwigdores a cambiar las cosas más rápidamente y con menos errores. El código correcto termina agrupado en los lugares correctos. Los objetos:

  • Se puede usar sin tener en cuenta qué implementación está presente
  • Deje en claro qué necesita ser cambiado y dónde
  • Aísle los cambios a algunas funciones de los cambios a otras funcionalidades: puede corregir X sin temor a interrumpir Y

hasattr vs isinstance

Tener que usar isinstance o hasattr en absoluto indica que el modelo de objeto está roto o lo estamos utilizando incorrectamente. Lo correcto es corregir el modelo de objetos o cambiar la forma en que lo estamos utilizando. Estas dos construcciones tienen el mismo efecto y en el imperativo “Necesito el código para hacer esto”, son equivalentes. Estructuralmente hay una gran diferencia. Al reunirse con este método por primera vez (o después de algunos meses de hacer otras cosas), la instancia transmite mucha más información sobre lo que realmente está sucediendo y qué más es posible. Hasattr no te dice nada.

Una larga historia de desarrollo nos aleja de FORTRAN y el código con un montón de conmutadores “quién soy yo”. Elegimos usar objetos porque sabemos que ayudan a facilitar el trabajo con el código. Al elegir hasattr, ofrecemos funcionalidad, sin embargo, nada está arreglado, el código está más dañado de lo que estaba antes de comenzar. Al agregar o cambiar esta funcionalidad en el futuro, tendremos que lidiar con el código que está desigualmente agrupado y tiene al menos dos principios de organización, algunos de ellos es donde debería estar y el rest se distribuye aleatoriamente en otros lugares. No hay nada que lo haga cohesionar. Este no es un error, sino un campo minado de posibles errores dispersos en cualquier ruta de ejecución que pase por su hasattr.

Así que si hay alguna opción, el orden es:

  1. Utilice el modelo de objetos o corríjalo o al menos descubra qué es lo que está mal y cómo solucionarlo
  2. Usa isinstance
  3. No use hasattr