Comprobar si una variable es una lista o tupla


En python, ¿cuál es la mejor manera de probar si una variable contiene una lista o una tupla? (IE. una colección)

Isinstance tan malo como se sugiere aquí? http://www.canonical.org / ~kragen / isinstance /

Actualización : la razón más común por la que quiero distinguir una lista de una cadena es cuando tengo un árbol / estructura de datos anidados indefinidamente profundos de listas de listas de listas de cadenas, etc. que estoy explorando con un algoritmo recursivo y necesito saber cuando he golpeado el nodos "hoja".

Author: interstar, 2010-02-02

11 answers

Siga adelante y use isinstance si lo necesita. Es algo malvado, ya que excluye secuencias personalizadas, iteradores y otras cosas que realmente pueda necesitar. Sin embargo, a veces necesita comportarse de manera diferente si alguien, por ejemplo, pasa una cadena. Mi preferencia sería comprobar explícitamente str o unicode así:

import types
isinstance(var, types.StringTypes)

N.b. No confundas types.StringType con types.StringTypes. Este último incorpora str y unicode objetos.

El módulo types es considerado por muchos como obsoleto a favor de simplemente comprobar directamente contra el tipo del objeto, por lo que si prefiere no usar lo anterior, puede alternativamente comprobar explícitamente contra str y unicode, así:

isinstance(var, (str, unicode)):

Editar:

, Mejor aún es:

isinstance(var, basestring)

End edit

Después de cualquiera de estos, puede volver a comportarse como si estuviera obteniendo una secuencia normal, dejando que las no secuencias generen excepciones apropiadas.

Ver lo que es "malo" acerca de la comprobación de tipos no es que desee comportarse de manera diferente para un determinado tipo de objeto, es que restringe artificialmente su función de hacer lo correcto con tipos de objetos inesperados que de otro modo harían lo correcto. Si tiene una reserva final que no está marcada, elimine esta restricción. Debe tenerse en cuenta que el exceso de comprobación de tipos es un olor a código que indica que es posible que desee hacer un poco de refactorización, pero eso no significa necesariamente que deba evitar desde el getgo.

 78
Author: jcdyer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-02 00:55:32
if type(x) is list:
    print 'a list'
elif type(x) is tuple:
    print 'a tuple'
else:
    print 'neither a tuple or a list'
 415
Author: wall-e,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-23 01:38:02

No hay nada de malo en usar isinstance siempre y cuando no sea redundante. Si una variable solo debe ser una lista/tupla, documente la interfaz y utilícela como tal. De lo contrario, un control es perfectamente razonable:

if isinstance(a, collections.Iterable):
    # use as a container
else:
    # not a container!

Este tipo de comprobación tiene algunos buenos casos de uso, como con la cadena estándar startswith / endswith métodos (aunque para ser precisos estos se implementan en C en CPython usando una comprobación explícita para ver si es una tupla-hay más de una forma de resolver este problema, como se menciona en el artículo al que se enlaza).

Una comprobación explícita es a menudo mejor que intentar usar el objeto como contenedor y manejar la excepción, lo que puede causar todo tipo de problemas con el código que se ejecuta parcial o innecesariamente.

 36
Author: Scott Griffiths,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-02 17:02:31

Documente el argumento como que necesita ser una secuencia, y utilícelo como una secuencia. No compruebes el tipo.

 14
Author: Ignacio Vazquez-Abrams,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-02 15:03:24

¿Qué tal: hasattr(a, "__iter__") ?

Indica si el objeto devuelto puede ser iterado como un generador. De forma predeterminada, las tuplas y las listas pueden, pero no los tipos de cadenas.

 10
Author: user1914881,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-11 20:53:16

Python usa "Duck typing", es decir, si una variable kwaks como un pato, debe ser un pato. En su caso, probablemente desee que sea iterable, o desea acceder al elemento en un determinado índice. Solo debes hacer esto: es decir, usar el objeto en for var: o var[idx] dentro de un bloque try, y si obtienes una excepción no es un pato...

 8
Author: Wim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-02 15:25:00

En Python 2.8 type(list) is list devuelve false
Yo sugeriría comparar el tipo de esta manera horrible:

if type(a) == type([]) :
  print "variable a is a list"

(bueno, al menos en mi sistema, usando anaconda en Mac OS X Yosemite)

 8
Author: Xanderite,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-05 15:46:13
>>> l = []
>>> l.__class__.__name__ in ('list', 'tuple')
True
 6
Author: tetra5,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-12-22 08:11:03

Si solo necesita saber si puede usar la notación foo[123] con la variable, puede verificar la existencia de un atributo __getitem__ (que es lo que python llama cuando accede por índice) con hasattr(foo, '__getitem__')

 3
Author: Geoff Reedy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-02 17:15:38

En principio, estoy de acuerdo con Ignacio, pero también puedes usar type para comprobar si algo es una tupla o una lista.

>>> a = (1,)
>>> type(a)
(type 'tuple')
>>> a = [1]
>>> type(a)
(type 'list')
 1
Author: Adam Crossland,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-02 15:10:45

Tiene que ser una prueba más compleja si realmente quieres manejar casi cualquier cosa como argumento de función.

type(a) != type('') and hasattr(a, "__iter__")

Aunque, por lo general es suficiente con simplemente deletrear que una función espera iterable y luego comprobar solo type(a) != type('').

También puede suceder que para una cadena tenga una ruta de procesamiento simple o que vaya a ser agradable y haga una división, etc. así que no quieres gritarle a las cuerdas y si alguien te envía algo raro, solo déjalo tener una excepción.

 1
Author: ZXX,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-09 01:51:35