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