4

I am writing a python script that process lists read from a file:

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

All works fine when l has more than one element.
However, when there is only one element in the list readFromFile returns l as a scalar and not as a list. Hence for i in l fails with error

object is not iterable

I have no control over readFromFile, and my question is how can I make python treat l as a alist even in the case where l has only a single element?

4

5 回答 5

4

Well a simple solution is

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

This will work even if you change what readListFromFile to return another iterable.

A one liner solution if it's guaranteed to be a str or a list (or other iterable) is just

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

just using a ternary operator.

On an aside, having a method called readList... not always returning a list is just evil.

于 2013-09-15T16:04:43.727 回答
2
l = readListFromFile(myFile)
if isinstance(l, list):
    for i in l :
        # do something to each element
else:
    #do that something mentioned above

or

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

or

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

and if you want a function:

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
于 2013-09-15T16:01:19.700 回答
1

Using a generator function and 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

Demo:

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

To handle any type of iterable you can use 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
于 2013-09-15T16:06:52.157 回答
1

You can put the check directly into the for-loop:

l = readListFromFile( myFile )
for i in (l if isinstance(l, list) else [l]):
    # Do something with i
于 2017-12-31T17:31:44.963 回答
0

If readFromFile returns a scalar rather than a list, then you can turn it to a list by yourself.

l = readListFromFile( myFile )
if not isinstance(l, list):
    l = [l]
for i in l :
    # do something to each element
于 2013-09-15T16:08:53.797 回答