8

I have a variable which can be a single string or a list of string. When the variable is a single string , the loop iterates it by char.

text = function() # the function method can return a single string or list of string
for word in text:
    print word+"/n"
# When it is a single string , it prints char by char.

I would want the loop to iterate only one time when it is a single string. I actually do not want to use other loop types. How can I do it with for each structure?

smci
  • 32,567
  • 20
  • 113
  • 146
vvvnn
  • 241
  • 2
  • 10

6 Answers6

11

It would be cleaner if your function would always return a list even one with only one element. I would highly recommend this if you can change your code there.

Otherwise add this line before your loop:

text = text if isinstance(text, list) else [text]

Also your variable names are confusing you should call "text" "word_list" or something just to better indicate the type required.

Requiring type checking usually indicates a problem of style.

Falk Schuetzenmeister
  • 1,497
  • 1
  • 16
  • 35
1

This should do it:

text = function() 
if isinstance(text, list):
    for word in text:
        print word + "/n"
else:
    print text + "/n"
Fejs
  • 2,734
  • 3
  • 21
  • 40
  • This is not a pythonic way of doing things, since if `function()` returns a tuple of strings then you're code would attempt to print the entire tuple as one word. – A Kareem Dec 27 '20 at 20:23
  • From the question, it is obvious that function returns either string or list of strings... Not a tuple. – Fejs Dec 29 '20 at 04:19
1

I settled on this because it puts an emphasis on preparation for a loop rather than a fundamental loop (re)design:

if type(thing) is str:
    x = [thing]
elif type(thing) is list:
    x = thing[:]

for i in x:
   ... do stuff ....
Rondo
  • 3,458
  • 28
  • 26
0

Despite duck typing being the norm, sometimes you simply must check the type of something. In this case, you expect something of instance basestring.

text = function()
if isinstance(text, basestring):
    print text
else:
    for word in text:
        print word
Brian
  • 7,394
  • 3
  • 25
  • 46
0

You need isinstance() method to check the type of value hold by your variable which as per document:

Return true if the object argument is an instance of the classinfo argument, or of a (direct, indirect or virtual) subclass thereof.

Using that you may create your custom function as:

import collections

def my_print(my_val):
    if isinstance(my_val, str):
        print my_val
    elif isinstance(my_val, collections.Iterable):  # OR, use `list` if you just want check for list object
        # To check object is iterable ^
        for val in my_val:
            print val
    else:
       raise TypeError('Unknown value')

Sample run:

>>> my_print('Hello')
Hello
>>> my_print(['Hello', 'World'])
Hello
World

instance() checks whether the object passed is the instance of passed class or not.

>>> isinstance('hello', str)
True
>>> isinstance('hello', list)
False

Alternatively, you may check for the type of variable using type() as:

>>> type('hello') == str
True
Moinuddin Quadri
  • 46,825
  • 13
  • 96
  • 126
0

Still doable by duck typing, you just need to use a method on a list that is not in a string or vice versa, and catch the exception, for example copy() is a method of list but not str.

text = function()
try:
    temp_text = text.copy()
    for word in text:
        print word
except AttributeError:
    print text

In the above code if function() returned a string text.copy() will rise an AttributeError exception and will not go through the for loop but go to the exception block and print the text as is, on the other hand if text.copy() is successful it means it is a list and it continues to the for loop to print each word of the list.

Dalvenjia
  • 1,953
  • 1
  • 12
  • 16
  • You could just check for the attribute instead of actually executing the method: assert(hasattr(text, 'copy')). You would get an AssertionError in case that would be false. Even though it is said that raising exceptions is better than type-checking, it would be interesting which one would perform better. – Falk Schuetzenmeister Nov 29 '16 at 18:55