Python comprueba si todos los elementos de una lista son del mismo tipo

¿Cómo es posible en Python verificar (sin verificar individualmente cada elemento si es posible) si los elementos de una lista son del mismo tipo?

Por ejemplo, me gustaría tener una función para verificar que todos los elementos de esta lista sean enteros (lo que es claramente falso):

x=[1, 2.5, 'a'] def checkIntegers(x): # return true if all elements are integers, false otherwise 

Intente usar all junto con isinstance :

 all(isinstance(x, int) for x in lst) 

Incluso puede verificar varios tipos con isinstance si es deseable:

 all(isinstance(x, (int, long)) for x in lst) 

No es que esto recoja clases heredadas también. p.ej:

 class MyInt(int): pass print(isinstance(MyInt('3'),int)) #True 

Si necesita limitarse a solo enteros, puede usar all(type(x) is int for x in lst) . Pero ese es un escenario MUY raro.


Una función divertida que podría escribir con esto es una que devolvería el tipo del primer elemento en una secuencia si todos los demás elementos son del mismo tipo:

 def homogeneous_type(seq): iseq = iter(seq) first_type = type(next(iseq)) return first_type if all( (type(x) is first_type) for x in iseq ) else False 

Esto funcionará para cualquier iterable arbitrario, pero consumirá “iteradores” en el proceso.

Otra función divertida en el mismo sentido que devuelve el conjunto de bases comunes:

 import inspect def common_bases(seq): iseq = iter(seq) bases = set(inspect.getmro(type(next(iseq)))) for item in iseq: bases = bases.intersection(inspect.getmro(type(item))) if not bases: break return bases 

Usando any() , no es necesario recorrer toda la lista. Simplemente rompa tan pronto como se encuentre el objeto que no es int o long :

 >>> not any(not isinstance(y,(int,long)) for y in [1,2,3]) True >>> not any(not isinstance(y,(int,long)) for y in [1,'a',2,3]) False 
 >>> def checkInt(l): return all(isinstance(i, (int, long)) for i in l) >>> checkInt([1,2,3]) True >>> checkInt(['a',1,2,3]) False >>> checkInt([1,2,3,238762384762364892364]) True 

La forma más sencilla de verificar si una lista está compuesta de elementos omógenos puede ser con la función groupby del módulo itertools:

 from itertools import groupby len(list(groupby(yourlist,lambda i:type(i)))) == 1 

Si esta diferencia es diferente de una, significa que encontró diferentes tipos de tipos en la lista. Esto tiene el problema de correr a través de toda la secuencia. Si quieres una versión perezosa puedes escribir una función para eso:

 def same(iterable): iterable = iter(iterable) try: first = type(next(iterable)) return all(isinstance(i,first) for i in iterable) except StopIteration: return True 

Esta función almacena el tipo del primer elemento y se detiene tan pronto como encuentre un tipo diferente en uno de los elementos de la lista.

Ambos métodos son muy sensibles al tipo, por lo que se verán como int y float diferentes, pero esto debería ser lo más cercano posible a su solicitud.

EDITAR:

Reemplazó el ciclo para cada uno con una llamada a todos, según lo sugerido por mgilson.

en caso de iterador de vacíos, devuelve True para ser consistente con el comportamiento de la función bulitin all.

Al combinar algunas de las respuestas ya dadas, el uso de una combinación de map (), type () y set () proporciona una respuesta bastante fácil de leer. Suponiendo que la limitación de no verificar los polymorphisms de tipo está bien. Tampoco es la respuesta más computacionalmente eficiente, pero permite verificar fácilmente si todos los elementos son del mismo tipo.

 # To check whether all elements in a list are integers set(map(type, [1,2,3])) == {int} # To check whether all elements are of the same type len(set(map(type, [1,2,3]))) == 1 

También puede usar type() si desea excluir subclases. Vea la diferencia entre isinstance() y type() :

 >>> not any(not type(y) is int for y in [1, 2, 3]) True >>> not any(not type(y) == int for y in [1, 'a', 2.3]) False 

Aunque puede que no quieras, porque esto será más frágil. Si y cambia su tipo a una subclase de int, este código se interrumpirá, mientras que isinstance() seguirá funcionando.

Está bien utilizarlo porque solo hay un en la memoria, por lo que deberían devolver la misma identidad si son del mismo tipo.

  def c(x): for i in x: if isinstance(i,str): return False if isinstance(i,float): return False return True 

Prefiero usar el mapa para un caso como este:

 from types import IntType In [21]: map((lambda x: isinstance(x, IntType)), x) Out[21]: [True, False, False]