Recipe 1.3. Testing Whether an Object Is String-like
Credit: Luther
Blissett
Problem
You need to test if an object, typically an argument to a function or
method you're writing, is a string (or more
precisely, whether the object is string-like).
Solution
A simple
and fast way to check whether something is a string or Unicode object
is to use the built-ins isinstance and
basestring, as
follows:
def isAString(anobj):
return isinstance(anobj, basestring)
Discussion
The first approach to solving this recipe's problem
that comes to many programmers' minds is
type-testing:
def isExactlyAString(anobj):However, this approach is pretty bad, as it willfully destroys one of
return type(anobj) is type('')
Python's greatest strengthssmooth,
signature-based polymorphism. This kind of test would reject Unicode
objects, instances of user-coded subclasses of
str, and instances of any user-coded type that is
meant to be "string-like".Using the isinstance built-in function, as
recommended in this recipe's Solution, is much
better. The built-in type basestring exists
exactly to enable this approach. basestring is a
common base class for the str and
unicode types, and any string-like type that user
code might define should also subclass basestring,
just to make sure that such isinstance testing
works as intended. basestring is essentially an
"empty" type, just like
object, so no cost is involved in subclassing it.Unfortunately, the canonical isinstance checking
fails to accept such clearly string-like objects as instances of the
UserString class from Python Standard Library
module UserString, since that class, alas, does
not inherit from basestring.
If you need to support such types, you can check directly whether an
object behaves like a stringfor example:
def isStringLike(anobj):This isStringLike function is slower and more
try: anobj + ''
except: return False
else: return True
complicated than the isAString function presented
in the "Solution", but it does
accept instances of UserString (and other
string-like types) as well as instances of str and
unicode.
The general
Python approach to type-checking is known as duck
typing: if it walks like a duck and quacks like a duck,
it's duck-like enough for our purposes. The
isStringLike function in this recipe goes only as
far as the quacks-like part, but that may be enough. If and when you
need to check for more string-like features of the object
anobj, it's easy to test a few
more properties by using a richer expression in the
TRy clausefor example, changing the clause
to:
try: anobj.lower( ) + anobj + ''In my experience, however, the simple test shown in the
isStringLike function usually does what I need. The
most Pythonic approach to type validation (or any validation task,
really) is just to try to perform whatever task you need to do,
detecting and handling any errors or exceptions that might result if
the situation is somehow invalidan approach known as
"it's easier to ask forgiveness
than permission" (EAFP).
try/except is the key tool in
enabling the EAFP style. Sometimes, as in this recipe, you may choose
some simple task, such as concatenation to the empty string, as a
stand-in for a much richer set of properties (such as, all the wealth
of operations and methods that string objects make available).
See Also
Documentation for the built-ins isinstance and
basestring in the Library
Reference and Python in a
Nutshell.