295 votos

¿Cuál es la mejor manera (idiomática) de comprobar el tipo de una variable de Python?

Necesito saber si una variable en Python es una cadena o un dict. ¿Hay algún problema con el siguiente código?

if type(x) == type(str()):
    do_something_with_a_string(x)
elif type(x) == type(dict()):
    do_somethting_with_a_dict(x)
else:
    raise ValueError

Actualización : He aceptado la respuesta de avisser (aunque cambiaré de opinión si alguien me explica por qué isinstance es preferible a type(x) is ).

Pero gracias a nakedfanatic por recordarme que a menudo es más limpio usar un dict (como declaración de caso) que una serie de if/elif/else.

Permítanme explicar mi caso de uso. Si una variable es una cadena, necesito ponerla en una lista. Si es un dict, necesito una lista de los valores únicos. Esto es lo que se me ocurrió:

def value_list(x):
    cases = {str: lambda t: [t],
             dict: lambda t: list(set(t.values()))}
    try:
        return cases[type(x)](x)
    except KeyError:
        return None

Si isinstance se prefiere, cómo se escribiría esto value_list() ¿función?

319voto

Suraj Barkale Puntos 1482

¿Qué ocurre si alguien pasa una cadena unicode a su función? ¿O una clase derivada de dict? ¿O una clase que implementa una interfaz similar a dict? El siguiente código cubre los dos primeros casos. Si usas Python 2.6 puedes usar collections.Mapping en lugar de dict según el ABC PEP .

def value_list(x):
    if isinstance(x, dict):
        return list(set(x.values()))
    elif isinstance(x, basestring):
        return [x]
    else:
        return None

62voto

type(dict()) dice "hacer un nuevo dict, y luego averiguar cuál es su tipo". Es más rápido decir simplemente dict . Pero si sólo quieres comprobar el tipo, una forma más idiomática es isinstance(x, dict) .

Tenga en cuenta que isinstance también incluye subclases (gracias Dustin ):

class D(dict):
    pass

d = D()
print("type(d) is dict", type(d) is dict)  # -> False
print("isinstance (d, dict)", isinstance(d, dict))  # -> True

35voto

Albert Visser Puntos 656

Los tipos incorporados en Python tienen nombres incorporados:

>>> s = "hallo"
>>> type(s) is str
True
>>> s = {}
>>> type(s) is dict
True

btw note el es operador. Sin embargo, la comprobación de tipo (si quieres llamarla así) suele hacerse envolviendo una prueba específica de tipo en una cláusula try-except, ya que lo importante no es tanto el tipo de la variable, sino si puedes hacer algo determinado con ella o no.

19voto

Dirk Stoop Puntos 2223

Isinstance es preferible a type porque también se evalúa como True cuando se compara la instancia de un objeto con su superclase, lo que básicamente significa que no tendrás que hacer un case especial en tu antiguo código para usarlo con subclases dict o str.

Por ejemplo:

 >>> class a_dict(dict):
 ...     pass
 ... 
 >>> type(a_dict()) == type(dict())
 False
 >>> isinstance(a_dict(), dict)
 True
 >>> 

Por supuesto, puede haber situaciones en las que no quieras este comportamiento, pero esas son -esperemos- mucho menos comunes que las situaciones en las que sí lo quieres.

8voto

JV. Puntos 1296

Creo que me decantaré por el enfoque de la tipografía de pato: "si camina como un pato, grazna como un pato, es un pato". De esta manera no tendrás que preocuparte de si la cadena es unicode o ascii.

Esto es lo que haré:

In [53]: s='somestring'

In [54]: u=u'someunicodestring'

In [55]: d={}

In [56]: for each in s,u,d:
    if hasattr(each, 'keys'):
        print list(set(each.values()))
    elif hasattr(each, 'lower'):
        print [each]
    else:
        print "error"
   ....:         
   ....:         
['somestring']
[u'someunicodestring']
[]

Los expertos aquí son bienvenidos a comentar sobre este tipo de uso de ducktyping, lo he estado usando, pero se introdujo en el concepto exacto detrás de él últimamente y estoy muy entusiasmado con él. Así que me gustaría saber si eso es una exageración para hacer.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X