¿Cómo puedo aplanar listas sin dividir cadenas?

Me gustaría aplanar listas que puedan contener otras listas sin separar cadenas. Por ejemplo:

In [39]: list( itertools.chain(*["cat", ["dog","bird"]]) ) Out[39]: ['c', 'a', 't', 'dog', 'bird'] 

y me gustaria

 ['cat', 'dog', 'bird'] 

 def flatten(foo): for x in foo: if hasattr(x, '__iter__'): for y in flatten(x): yield y else: yield x 

(Las cadenas convenientemente no tienen realmente un atributo __iter__ , a diferencia de casi todos los demás objetos iterables en Python. Tenga en cuenta que esto cambia en Python 3, por lo que el código anterior solo funcionará en Python 2.x.)

Versión para Python 3.x:

 def flatten(foo): for x in foo: if hasattr(x, '__iter__') and not isinstance(x, str): for y in flatten(x): yield y else: yield x 

Una ligera modificación de la respuesta de orip que evita crear una lista intermedia:

 import itertools items = ['cat',['dog','bird']] itertools.chain.from_iterable(itertools.repeat(x,1) if isinstance(x,str) else x for x in items) 

una forma de fuerza bruta sería envolver la cadena en su propia lista, luego usar itertools.chain

 >>> l = ["cat", ["dog","bird"]] >>> l2 = [([x] if isinstance(x,str) else x) for x in l] >>> list(itertools.chain(*l2)) ['cat', 'dog', 'bird'] 
 def squash(L): if L==[]: return [] elif type(L[0]) == type(""): M = squash(L[1:]) M.insert(0, L[0]) return M elif type(L[0]) == type([]): M = squash(L[0]) M.append(squash(L[1:])) return M def flatten(L): return [i for i in squash(L) if i!= []] >> flatten(["cat", ["dog","bird"]]) ['cat', 'dog', 'bird'] 

Espero que esto ayude