python - tuplas - Prueba si una variable es una lista o tupla
range python (11)
En Python, ¿cuál es la mejor manera de probar si una variable contiene una lista o una tupla? (es decir, una colección)
¿Es la instancia tan malvada como se sugiere aquí? http://www.canonical.org/~kragen/isinstance/
Actualización: la razón más común por la que deseo distinguir una lista de una cadena es cuando tengo una estructura de árbol / datos anidada profundamente indefinidamente de listas de listas de cadenas, etc. que estoy explorando con un algoritmo recursivo y que necesito para saber cuándo he golpeado los nodos de "hoja".
¿Qué tal: hasattr(a, "__iter__")
?
Indica si el objeto devuelto puede repetirse como generador. Por defecto, las tuplas y listas pueden, pero no los tipos de cadena.
Documente el argumento como que necesita ser una secuencia, y úselo como una secuencia. No verifique el tipo.
En Python 2.8 type(list) is list
devuelve false
Sugeriría comparar el tipo de esta manera horrible:
if type(a) == type([]) :
print "variable a is a list"
(al menos en mi sistema, usando anaconda en Mac OS X Yosemite)
En principio, estoy de acuerdo con Ignacio, arriba, pero también puedes usar el tipo para verificar si algo es una tupla o una lista.
>>> a = (1,)
>>> type(a)
(type ''tuple'')
>>> a = [1]
>>> type(a)
(type ''list'')
No hay nada de malo en usar isinstance
siempre que no sea redundante. Si una variable solo debe ser una lista / tupla, documente la interfaz y simplemente úsela como tal. De lo contrario, un cheque es perfectamente razonable:
if isinstance(a, collections.Iterable):
# use as a container
else:
# not a container!
Este tipo de verificación tiene algunos buenos casos de uso, como con la cadena estándar startswith / endswith methods (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 para resolver este problema, como se menciona en el artículo al que se vincula).
A menudo, una comprobación explícita es mejor que intentar usar el objeto como contenedor y manejar la excepción, que puede causar todo tipo de problemas con la ejecución parcial o innecesaria del código.
Python usa "Duck typing", es decir, si una variable se mueve como un pato, debe ser un pato. En su caso, es probable que desee que sea iterable, o si desea acceder al elemento en un determinado índice. Simplemente debes hacer esto: es decir, usar el objeto for var:
o var[idx]
dentro de un bloque try
, y si obtienes una excepción, no era un pato ...
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 llama python cuando accede por índice) con hasattr(foo, ''__getitem__'')
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 para deletrear que una función espera iterable y luego solo verificar type(a) != type('''')
.
También puede suceder que para una cadena tengas una ruta de procesamiento simple o serás agradable y harás una división, etc., por lo que no querrás gritarle a nadie y si alguien te envía algo raro, solo déjalo tener. una excepción.
Siga adelante y use isinstance
si lo necesita. Es algo malo, ya que excluye secuencias personalizadas, iteradores y otras cosas que realmente podría necesitar. Sin embargo, a veces debe comportarse de manera diferente si alguien, por ejemplo, pasa una cadena. Mi preferencia allí sería verificar explícitamente str
o unicode
así:
import types
isinstance(var, types.StringTypes)
NB No confundas types.StringTypes
. types.StringType
para types.StringTypes
. Este último incorpora objetos str
y unicode
.
El módulo de types
es considerado por muchos como obsoleto a favor de simplemente verificar directamente contra el tipo de objeto, por lo que si prefieres no usar lo anterior, alternativamente puedes verificar explícitamente contra str
y unicode
, así:
isinstance(var, (str, unicode)):
Editar:
Mejor aún es:
isinstance(var, basestring)
Finalizar edición
Después de cualquiera de estos, puede volver a comportarse como si estuviera obteniendo una secuencia normal, dejando que las secuencias no presenten las excepciones apropiadas.
Ver lo que es "malo" sobre la comprobación de tipos no es que desee comportarse de manera diferente para un determinado tipo de objeto, sino que restringe artificialmente su función para que no haga lo correcto con tipos de objetos inesperados que de lo contrario harían lo correcto. Si tiene una reserva final que no está verificada por tipo, elimina esta restricción. Debe tenerse en cuenta que una verificación de tipo excesiva es un olor a código que indica que es posible que desee realizar alguna refactorización, pero eso no significa necesariamente que deba evitarla desde el principio.
>>> l = []
>>> l.__class__.__name__ in (''list'', ''tuple'')
True
if type(x) is list:
print ''a list''
elif type(x) is tuple:
print ''a tuple''
else:
print ''neither a tuple or a list''