Check if input is a list/tuple of strings or a single string
Asked Answered
C

9

76

I've a method that I want to be able to accept either a single string (a path, but not necessarily one that exists on the machine running the code) or a list/tuple of strings.

Given that strings act as lists of characters, how can I tell which kind the method has received?

I'd like to be able to accept either standard or unicode strings for a single entry, and either lists or tuples for multiple, so isinstance doesn't seem to be the answer unless I'm missing a clever trick with it (like taking advantage of common ancestor classes?).

Python version is 2.5

Condone answered 28/5, 2009 at 19:35 Comment(2)
sample input/output makes such questions much easier to interpretCoauthor
Here the simple answer https://mcmap.net/q/266000/-check-if-input-is-a-list-tuple-of-strings-or-a-single-string -- is not obvious due to the py2-3 changes.Roulers
C
87

You can check if a variable is a string or unicode string with

  • Python 3:
    isinstance(some_object, str)
  • Python 2:
    isinstance(some_object, basestring)

This will return True for both strings and unicode strings

As you are using python 2.5, you could do something like this:

if isinstance(some_object, basestring):
    ...
elif all(isinstance(item, basestring) for item in some_object): # check iterable for stringness of all items. Will raise TypeError if some_object is not iterable
    ...
else:
    raise TypeError # or something along that line

Stringness is probably not a word, but I hope you get the idea

Colbert answered 28/5, 2009 at 19:39 Comment(4)
Aha! I thought there must be some common ancestry somewhere, I just couldn't find the reference...Condone
python 3 has removed basestring. Use str (or bytes, if you have bytes...) insteadChelsiechelsy
Using the six library, you can use six.string_types in place of str or basestring for compatibility.Eclogue
isinstance and type are to avoid in production due to their performance. Duck typing should be used instead.Wellbred
Z
34

isinstance is an option:

In [2]: isinstance("a", str)
Out[2]: True

In [3]: isinstance([], str)
Out[3]: False

In [4]: isinstance([], list)
Out[4]: True

In [5]: isinstance("", list)
Out[5]: False
Zimmer answered 28/5, 2009 at 19:41 Comment(0)
A
20

Type checking:

def func(arg):
    if not isinstance(arg, (list, tuple)):
        arg = [arg]
    # process

func('abc')
func(['abc', '123'])

Varargs:

def func(*arg):
    # process

func('abc')
func('abc', '123')
func(*['abc', '123'])
Albertalberta answered 28/5, 2009 at 19:39 Comment(0)
R
6

As I like to keep things simple, here is the shortest form that is compatible with both 2.x and 3.x:

# trick for py2/3 compatibility
if 'basestring' not in globals():
   basestring = str

v = "xx"

if isinstance(v, basestring):
   print("is string")
Roulers answered 7/11, 2014 at 9:10 Comment(0)
M
5
>>> type('abc') is str
True
>>> type(['abc']) is str
False

This code is compatible with Python 2 and 3

Modernize answered 17/5, 2017 at 19:1 Comment(2)
Seems to be the most concise and clear way, as of today.Tran
With python2, this will miss unicode strings, which is why the python2 examples use basestring. e.g. type(u'abc') is str -> FalseChelsiechelsy
I
4

I'm surprised no one gave an answer with duck typing, but gave unclear or highly type-dependent or version-dependent answers. Also, the accepted answer unfortunately has separate code for Python 2 and 3. Python uses and encourages duck typing, so (one line more than sorin's "shortest form" which is not duck typing) I instead recommend:

def is_str(v):
    return hasattr(v, 'lower')

...and whatever other attributes you want to use (remember the quotes). That way, client code using your software can send whatever kind of string they want as long as it has the interface your software requires. Duck typing is more useful in this way for other types, but it is generally the best way.

Or you could also do this (or generally check for AttributeError and take some other action):

def is_str(v):
    try:
        vL = v.lower()
    except AttributeError:
        return False
    return True
Intermixture answered 25/11, 2020 at 14:27 Comment(3)
But if you're writing an is_str function, is it really duck typing at that point? I suppose, but if you need to use .lower(), then just use .lower() and catch the potential AttributeError. No need to waste cycles checking first. The problem is, sometimes you aren't calling any specific string methods. E.g. maybe you are passing the string directly to another function. In an ideal world, that function would raise an exception for non-strings, but you can't always count on it. Sometimes, isinstance() really is the ideal solution.Punkie
@DominickPastore Yes, you wouldn't use my function (but it's an example & directly answers the question). Before it I said "or you could..." not that using the function was duck typing. That would be, as you say, to put the body of my function (or do what you are saying or what I said before the function) inline & form code around it. I disagree about isinstance--The point of duck typing & why Python uses it is to not error out when an object does what you want to do, but instead handle individual exceptions--If it "quacks like a duck" it is a duck (or you can count on it for the use case).Intermixture
Notice I said "put the body of my function" inline, not the definition. You would just use the code from it not define it, then you'd modify the code to do things specific to your code instead of what the function does.Intermixture
J
3

Check the type with isinstance(arg, basestring)

Jovitajovitah answered 28/5, 2009 at 19:39 Comment(0)
C
1

Have you considered varargs syntax? I'm not really sure if this is what you're asking, but would something like this question be along your lines?

Coauthor answered 28/5, 2009 at 19:36 Comment(1)
Wouldn't that just force the caller to specify which was being sent? I'd prefer to avoid that if possible. (And I'm also intrigued as to whether what I want to do is possible in an elegant way...)Condone
B
-2

Can't you do:

(i == list (i) or i == tuple (i))

It would reply if the input is tuple or list. The only issue is that it doesn't work properly with a tuple holding only one variable.

Boletus answered 13/10, 2016 at 23:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.