¿Cómo verificar si un objeto tiene un atributo?

8 minutos de lectura

Avatar de usuario de Lucas Gabriel Sánchez
lucas gabriel sánchez

¿Cómo compruebo si un objeto tiene algún atributo? Por ejemplo:

>>> a = SomeClass()
>>> a.property
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: SomeClass instance has no attribute 'property'

¿Cómo puedo saber si a tiene el atributo property antes de usarlo?

  • Cuando tu dices “decir si a tiene la propiedad de atributo antes de usarlo?” ¿Quieres una función que devuelva un valor booleano (como hasattr() regresa) o está bien lanzar un AttributeError ¿excepción?

    – smci

    28 de febrero a las 4:04


  • Además, en realidad no nombre su atributo ‘propiedad’, porque Python tiene property decorador y construido también, y esos son ligeramente diferentes a los atributos/métodos normales.

    – smci

    28 de febrero a las 4:07

Avatar de usuario de Jarret Hardie
Jarret Hardie

Probar hasattr():

if hasattr(a, 'property'):
    a.property

¡Vea la respuesta de zweiterlinde a continuación, quien ofrece buenos consejos sobre cómo pedir perdón! ¡Un enfoque muy pitónico!

La práctica general en python es que, si es probable que la propiedad esté allí la mayor parte del tiempo, simplemente llámela y deje que la excepción se propague o atrape con un bloque try/except. Esto probablemente será más rápido que hasattr. Si es probable que la propiedad no esté allí la mayor parte del tiempo, o si no está seguro, utilice hasattr probablemente será más rápido que caer repetidamente en un bloque de excepción.

  • Parece estar funcionando para verificar funciones en el espacio de nombres también, por ejemplo: import string hasattr(string, "lower")

    – riviera

    8 de abril de 2011 a las 12:54


  • hasattr es exactamente lo mismo que usar try/except AttributeError: la cadena de documentación de hasattr (en Python 2.7) dice que usa excepciones de captura manual de getattr.

    –Jeff Tratner

    27 de abril de 2012 a las 3:04

  • @JeffTratner: hasattr desafortunadamente no es exactamente lo mismo que un try: ... except AttributeError: en Python 2.x desde hasattr voluntad atrapar todas las excepciones. Consulte mi respuesta para ver un ejemplo y una solución sencilla.

    – Martín Geisler

    24 de abril de 2013 a las 7:44

  • hasattr no funciona si su objeto es un ‘dict’. Use el método in operator o haskey en esos casos.

    – Anand Shiva

    4 de abril de 2021 a las 12:13

  • se puede hacer por atributo para self? me gusta if not hasattr(self, 'property') dentro de __init__() de la creación del objeto

    – alper

    14 de septiembre de 2021 a las 3:51


avatar de usuario de zweiterlinde
zweiterlinde

Como respondió Jarret Hardie, hasattr hará el truco. Sin embargo, me gustaría agregar que muchos en la comunidad de Python recomiendan una estrategia de “más fácil pedir perdón que permiso” (EAFP) en lugar de “mirar antes de saltar” (LBYL). Vea estas referencias:

EAFP vs LBYL (Fue Re: Un poco decepcionado hasta ahora)
EAFP vs. LBYL @Code Like a Pythonista: Python idiomático

es decir:

try:
    doStuff(a.property)
except AttributeError:
    otherStuff()

… es preferible a:

if hasattr(a, 'property'):
    doStuff(a.property)
else:
    otherStuff()

  • Pero, ¿cómo se comprueba que fue la propiedad a la que causó AttributeError y no algo en doStuff()? Parece que no. Creo que es realmente más fácil pedir perdón, pero muchas veces también es incorrecto.

    – jpalecek

    14 de abril de 2009 a las 13:22

  • EAFP parece… una locura. HasAttr telegrafía a los futuros programadores de mantenimiento que está comprobando un atributo en particular. Obtener una excepción no les dice nada a los futuros programadores y podría llevar a alguien a la madriguera del conejo.

    –Ethan Heilman

    14/10/2010 a las 18:54

  • @e5: tienes razón en este caso, pero en muchos casos EAFP es la única opción correcta. Por ejemplo, si verifica la existencia de un archivo y luego lo abre, esperando que definitivamente existirá, su código es incorrecto: el archivo puede ser eliminado o renombrado entre la verificación y el uso. Esto se denomina error TOCTOU (Tiempo de verificación hasta el momento de uso) y, además de causar fallas, también puede ser una fuente de vulnerabilidades de seguridad.

    – Máx.

    1 de junio de 2011 a las 13:08

  • @EthanHeilman solo es una locura cuando hay ambigüedad en el origen de la excepción, lo que se puede evitar con un buen diseño en la mayoría de los casos. La estructuración de la lógica en capas dentro de try/except/finally generalmente hace que la lógica sea más robusta (menos propensa a errores del programador) que ensuciar el código con verificaciones if preventivas para cada pieza de código consumidor. También hace que los errores sean muy explícitos y permite a los programadores consumidores la opción de tratar con ellos directamente.

    – Pedro M. Elías

    2 de enero de 2013 a las 16:23

  • La mayoría de las quejas de ambigüedad aquí se deben simplemente a que el código de muestra está mal estructurado. Lo único dentro de la try: debe ser el intento de acceso al atributo; no hay razón para envolver la ejecución de doStuff también. Sin embargo, todavía existe cierto potencial de ambigüedad: si property es una propiedad calculada en lugar de un atributo simple, su implementación podría generar AttributeError internamente. Es por eso que en casi todas las situaciones reales como esta, getattr es preferible a cualquiera hasattr o atrapar AttributeError.

    –Carl Meyer

    24/09/2013 a las 20:21

Avatar de usuario de Carl Meyer
carl meyer

Puedes usar hasattr() o atrapar AttributeErrorpero si realmente solo desea el valor del atributo con un valor predeterminado si no está allí, la mejor opción es usar getattr():

getattr(a, 'property', 'default value')

  • Esto resuelve los dos problemas antes mencionados: a) La ambigüedad de la fuente de un posible AttributeError, b) Preservar el enfoque EAFP.

    – Pedro M. Elías

    2 de enero de 2013 a las 16:17

  • También es el 25% de las líneas de código. Seguramente esta tiene que ser la mejor solución.

    – fatuhoku

    24 de septiembre de 2013 a las 11:36

  • Esta es la mejor solución “si realmente solo desea el valor del atributo con un valor predeterminado”. Aunque creo que esto es lo que muchas personas realmente quieren cuando dicen que quieren detectar si un atributo está presente, el OP en realidad solicitó lo último, por lo que es razonable que las respuestas directas a esa pregunta (hasattr, AttributeError) aparezcan más arriba. .

    –Carl Meyer

    1 de diciembre de 2015 a las 5:48

  • Se votó a favor por mencionar “propiedad predeterminada”. ¡Hubo momentos en que necesité esto, pero lo olvidé!

    – Vexen Crabtree

    24 de junio de 2021 a las 11:56

avatar de usuario de batbrat
mocoso

creo que lo que buscas es hasattr. Sin embargo, recomendaría algo como esto si desea detectar propiedades de pitón

try:
    getattr(someObject, 'someProperty')         
except AttributeError:
    print "Doesn't exist"
else
    print "Exists"

La desventaja aquí es que los errores de atributo en las propiedades __get__ el código también se captura.

De lo contrario, haz-

if hasattr(someObject, 'someProp'):
    #Access someProp/ set someProp
    pass

Documentos:http://docs.python.org/library/functions.html
Advertencia:

El motivo de mi recomendación es que hasattr no detecta propiedades.
Enlace:http://mail.python.org/pipermail/python-dev/2005-December/058498.html

Según pydoc, hasattr(obj, prop) simplemente llama a getattr(obj, prop) y detecta excepciones. Por lo tanto, es tan válido envolver el acceso al atributo con una declaración de prueba y detectar AttributeError como usar hasattr() de antemano.

a = SomeClass()
try:
    return a.fake_prop
except AttributeError:
    return default_value

  • Bueno hasattr en realidad quizás optimizado Por ejemplo, con pypy.

    – odinho – Velmont

    18 de agosto de 2011 a las 17:37


  • +1. esto es incluso más seguro que usar hasattr cuando SomeClass anula __getattr__ ya que hasattr cogerá todos excepciones en Python 2.x, no solo AttributeError como esperarías. Esto se solucionó en Python 3.2; consulte mi otra respuesta para obtener una solución sencilla.

    – Martín Geisler

    24 de abril de 2013 a las 7:47


Avatar de usuario de Maico
maico

Me gustaría sugerir evitar esto:

try:
    doStuff(a.property)
except AttributeError:
    otherStuff()

El usuario @jpalecek lo mencionó: Si un AttributeError ocurre dentro doStuff()estás perdido.

Tal vez este enfoque es mejor:

try:
    val = a.property
except AttributeError:
    otherStuff()
else:
    doStuff(val)

  • Bueno hasattr en realidad quizás optimizado Por ejemplo, con pypy.

    – odinho – Velmont

    18 de agosto de 2011 a las 17:37


  • +1. esto es incluso más seguro que usar hasattr cuando SomeClass anula __getattr__ ya que hasattr cogerá todos excepciones en Python 2.x, no solo AttributeError como esperarías. Esto se solucionó en Python 3.2; consulte mi otra respuesta para obtener una solución sencilla.

    – Martín Geisler

    24 de abril de 2013 a las 7:47


EDITAR:Este enfoque tiene serias limitaciones. Debería funcionar si el objeto es un iterable una. Por favor revise los comentarios a continuación.

Si estás usando Pitón 3.6 o superior como yo, hay una alternativa conveniente para verificar si un objeto tiene un atributo en particular:

if 'attr1' in obj1:
    print("attr1 = {}".format(obj1["attr1"]))

Sin embargo, no estoy seguro de cuál es el mejor enfoque en este momento. usando hasattr()usando getattr() o usando in. Los comentarios son bienvenidos.

  • in la palabra clave funciona para verificar tipos iterables. Por ejemplo, 'foo' in None lanza el error TypeError: argument of type 'NoneType' is not iterable. La solución es verificar si el tipo es iterable antes de usar in. Después de corregir los casos extremos como el tipo no iterable, probablemente sea mejor usar hasattr() porque está diseñado para manejar los casos extremos.

    – Seth Difley

    5 de octubre de 2017 a las 13:06

  • Esto no tiene nada que ver con el acceso a los atributos. No tengo idea de cómo fue votado. La única similitud que tiene para atribuir el acceso es si está utilizando dict como un “objeto liviano”, similar al diseño de objetos de JavaScript, pero la mayoría de las clases normales no admitirán esto en general (obteniendo una variante del error mencionado por @SethDifley).

    – ShadowRanger

    25 de abril de 2018 a las 19:37


¿Ha sido útil esta solución?