What is the best way to check whether a given object is of a given type? How about checking whether the object inherits from a given type?
Let's say I have an object o
. How do I check whether it's a str
?
What is the best way to check whether a given object is of a given type? How about checking whether the object inherits from a given type?
Let's say I have an object o
. How do I check whether it's a str
?
isinstance(o, str)
will returntrue
ifo
is anstr
or is of a type that inherits fromstr
.type(o) is str
will returntrue
if and only ifo
is a str. It will returnfalse
ifo
is of a type that inherits fromstr
. ----Link to docs
To Hugo:
You probably mean
list
rather thanarray
, but that points to the whole problem with type checking - you don't want to know if the object in question is a list, you want to know if it's some kind of sequence or if it's a single object. So try to use it like a sequence.Say you want to add the object to an existing sequence, or if it's a sequence of objects, add them all
One trick with this is if you are working with strings and/or sequences of strings - that's tricky, as a string is often thought of as a single object, but it's also a sequence of characters. Worse than that, as it's really a sequence of single-length strings.
I usually choose to design my API so that it only accepts either a single value or a sequence - it makes things easier. It's not hard to put a
[ ]
around your single value when you pass it in if need be.(Though this can cause errors with strings, as they do look like (are) sequences.)
After the question was asked and answered, type hints were added to Python. Type hints in Python allow types to be checked but in a very different way from statically typed languages. Type hints in Python associate the expected types of arguments with functions as runtime accessible data associated with functions and this allows for types to be checked. Example of type hint syntax:
In this case we want an error to be triggered for
foo('oops')
since the annotated type of the argument isint
. The added type hint does not cause an error to occur when the script is run normally. However, it adds attributes to the function describing the expected types that other programs can query and use to check for type errors.One of these other programs that can be used to find the type error is
mypy
:(You might need to install
mypy
from your package manager. I don't think it comes with CPython but seems to have some level of "officialness".)Type checking this way is different from type checking in statically typed compiled languages. Because types are dynamic in Python, type checking must be done at runtime, which imposes a cost -- even on correct programs -- if we insist that it happen at every chance. Explicit type checks may also be more restrictive than needed and cause unnecessary errors (e.g. does the argument really need to be of exactly
list
type or is anything iterable sufficient?).The upside of explicit type checking is that it can catch errors earlier and give clearer error messages than duck typing. The exact requirements of a duck type can only be expressed with external documentation (hopefully it's thorough and accurate) and errors from incompatible types can occur far from where they originate.
Python's type hints are meant to offer a compromise where types can be specified and checked but there is no additional cost during usual code execution.
The
typing
package offers type variables that can be used in type hints to express needed behaviors without requiring particular types. For example, it includes variables such asIterable
andCallable
for hints to specify the need for any type with those behaviors.While type hints are the most Pythonic way to check types, it's often even more Pythonic to not check types at all and rely on duck typing. Type hints are relatively new and the jury is still out on when they're the most Pythonic solution. A relatively uncontroversial but very general comparison: Type hints provide a form of documentation that can be enforced, allow code to generate earlier and easier to understand errors, can catch errors that duck typing can't, and can be checked statically (in an unusual sense but it's still outside of runtime). On the other hand, duck typing has been the Pythonic way for a long time, doesn't impose the cognitive overhead of static typing, is less verbose, and will accept all viable types and then some.
I think the cool thing about using a dynamic language like Python is you really shouldn't have to check something like that.
I would just call the required methods on your object and catch an
AttributeError
. Later on this will allow you to call your methods with other (seemingly unrelated) objects to accomplish different tasks, such as mocking an object for testing.I've used this a lot when getting data off the web with
urllib2.urlopen()
which returns a file like object. This can in turn can be passed to almost any method that reads from a file, because it implements the sameread()
method as a real file.But I'm sure there is a time and place for using
isinstance()
, otherwise it probably wouldn't be there :)You can check with the below line to check which character type the given value is: