Python: Check if an object is a list of strings

39.4k views Asked by At

How to check if an object is a list of strings? I could only check if an object is string as such:

def checktype(obj):
  if isinstance(obj,str):
    print "It's a string"

obj1 = ['foo','bar','bar','black','sheet']
obj2 = [1,2,3,4,5,'bar']
obj3 = 'bar'

for i in [obj1,obj2,obj3]:
  checktype(i)

Desired output:

It's a list of strings
It's not a list of strings or a single string
It's a single string
6

There are 6 answers

12
Sukrit Kalra On BEST ANSWER

Something like this, I presume? You could do some checks to see if it's a single string.

>>> def checktype(obj):
        return bool(obj) and all(isinstance(elem, basestring) for elem in obj)

>>> obj1 = ['foo','bar','bar','black','sheet']
>>> obj2 = [1,2,3,4,5,'bar']
>>> obj3 = 'bar'
>>> for i in [obj1, obj2, obj3] :
        print checktype(i)


True
False
True

Why check for basestring instead of str?

You should check for basestring instead of str since it's a common class from which both the str and unicode types inherit from. Checking only the str leaves out the unicode types.

As per Steven Rumbalski's suggestions, if you need to specifically check for a list of strings, you could do.

>>> def is_list_of_strings(lst):
        return bool(lst) and not isinstance(lst, basestring) and all(isinstance(elem, basestring) for elem in lst)
        # You could break it down into `if-else` constructs to make it clearer to read.

>>> for i in [obj1, obj2, obj3] :
        print is_list_of_strings(i)


True
False
False

EDIT - As per abarnert's suggestion, you could also check for a list instead of not isinstance(lst, basestring), the code would get rewritten as.

>>> def is_list_of_strings(lst):
        return bool(lst) and isinstance(lst, list) and all(isinstance(elem, basestring) for elem in lst)
        # You could break it down into `if-else` constructs to make it clearer to read.

>>> for i in [obj1, obj2, obj3] :
        print is_list_of_strings(i)


True
False
False

Moving away from one liners, we could use.

>>> def is_list_of_strings(lst):
        if lst and isinstance(lst, list):
            return all(isinstance(elem, basestring) for elem in lst)
        else:
            return False
0
Mike Housky On

The answers I've read so far raise exepctions when given a non-list that isn't a string...and isn't iterable either. That question is addressed in:

In Python, how do I determine if an object is iterable?

Taking the duck-typing approach:

def categorize(x):
    result = "not a string or list of strings"
    if isinstance(x, basestring):
        return "It's a single string"
    try:
        if all(isinstance(y, basestring) for y in x):
            return "It's a list of strings"
    except TypeError:
        pass
    return "It's not a list of strings or a single string"

data = [ 5, "xyzzy", list("xyzzy"), ['1', '23', 456]]
for x in data:
    print x, categorize(x)

Output:

5 It's not a list of strings or a single string
xyzzy It's a single string
['x', 'y', 'z', 'z', 'y'] It's a list of strings
['1', '23', 456] It's not a list of strings or a single string
7
AudioBubble On

To test if all the items in a list are strings, use the all built-in and a generator:

if all(isinstance(s, str) for s in lis):

Note though that, if your list is empty, this will still return True since that is technically a list of 0 strings. However, since you want to consider [] as being False, you will need to do this:

if lis and all(isinstance(s, str) for s in lis):

So, your function should be something like this:

def checktype(obj):
    # This if statement makes sure input is a list that is not empty
    if obj and isinstance(obj, list): 
        return all(isinstance(s, str) for s in obj)
    else:
        return False

This function will only return True if its input is a list that is not empty and that is composed entirely of strings. Anything else (such as [], ['a', 1], ('a', 'b'), etc) will make it return False.

Also, using all in this way has an added bonus in that it stops checking on the first item it finds that returns False (is not a string). This allows you to work with very large lists quite efficiently.

0
HoangYell On

You may also convert all elements to str: list(map(str, [1,2,3]))

Result: ['1', '2', '3']

0
Asclepius On

This answer is for Python 3. If for example the variable name is pins:

if not (pins and isinstance(pins, list) and all(isinstance(pin, str) for pin in pins)):
    raise TypeError('pins must be a list of one or more strings.')

It checks for three things:

  1. Is is non-empty?
  2. Is it a list?
  3. Does it contain strings?

If you also need to check for uniqueness of the strings, include this fourth check:

and (len(pins) == len(set(pins)))
0
HeyMan On

As a one liner:

assert all(map(lambda x: isinstance(x, str), my_list))