python: tratar un escalar como una lista de un elemento

Estoy escribiendo una secuencia de comandos de python que procesa listas de lectura de un archivo:

l = readListFromFile( myFile ) for i in l : # do something to each element 

Todo funciona bien cuando l más de un elemento.
Sin embargo, cuando solo hay un elemento en la lista, readFromFile devuelve l como un escalar y no como una lista. Por lo tanto for i in l falla con error

objeto no es iterable

No tengo control sobre readFromFile , y mi pregunta es ¿cómo puedo hacer que python trate l como una lista, incluso en el caso de que solo tenga un elemento?

Bueno, una solución simple es

 l = readListFromFile(myFile) try: i = iter(l) if isinstance(l, str): i = l except TypeError: i = [l] for .... in i 

Esto funcionará incluso si cambia lo que readListFromFile para devolver otro iterable.

Una solución de una línea, si está garantizada como una str o una lista (u otra iterable) es simplemente

 l = readListFromFile(myFile) for e in [l] if isinstance(l, str) else l: 

Simplemente utilizando un operador ternario.

En un lado, tener un método llamado readList … no siempre devolver una lista es simplemente malo.

 l = readListFromFile(myFile) if isinstance(l, list): for i in l : # do something to each element else: #do that something mentioned above 

o

 l = readListFromFile(myFile) if isinstance(l, str): l = [l] for i in l: #do that same something as above 

o

 l = readListFromFile(myFile) try: for i in l: #do that something except: #do that something with the value 

Y si quieres una función:

 def get_me_a_list(var): if isinstance(var, list): return var return [var] l = get_me_a_list(readListFromFile(myFile)) for i in l: #do your something 

Usando una función de generador e isinstance :

 def solve(lis): if isinstance(lis, list): for item in lis: #use just `yield from lis` in py3.x yield item else: yield lis 

Manifestación:

 >>> for item in solve(1): ... print item ... 1 >>> for item in solve([1, 2, 3]): print item ... 1 2 3 

Para manejar cualquier tipo de iterable puedes usar collections.Iterable :

 from collections import Iterable def solve(lis): if isinstance(lis, Iterable) and not isinstance(lis, basestring): for item in lis: #use just `yield from lis` in py3.x yield item else: yield lis 

Puedes poner el cheque directamente en el bucle for:

 l = readListFromFile( myFile ) for i in (l if isinstance(l, list) else [l]): # Do something with i 

Si readFromFile devuelve un escalar en lugar de una list , puede convertirlo en una list por sí mismo.

 l = readListFromFile( myFile ) if not isinstance(l, list): l = [l] for i in l : # do something to each element