How would you check if a variable is a dictionary in Python?
This is an excellent question, but it is unfortunate that the most upvoted answer leads with a poor recommendation, type(obj) is dict
.
(Note that you should also not use dict
as a variable name - it's the name of the builtin object.)
If you are writing code that will be imported and used by others, do not presume that they will use the dict builtin directly - making that presumption makes your code more inflexible and in this case, create easily hidden bugs that would not error the program out.
I strongly suggest, for the purposes of correctness, maintainability, and flexibility for future users, never having less flexible, unidiomatic expressions in your code when there are more flexible, idiomatic expressions.
is
is a test for object identity. It does not support inheritance, it does not support any abstraction, and it does not support the interface.
So I will provide several options that do.
This is the first recommendation I would make, because it allows for users to supply their own subclass of dict, or a OrderedDict
, defaultdict
, or Counter
from the collections module:
if isinstance(any_object, dict):
But there are even more flexible options.
from collections.abc import Mapping
if isinstance(any_object, Mapping):
This allows the user of your code to use their own custom implementation of an abstract Mapping, which also includes any subclass of dict
, and still get the correct behavior.
You commonly hear the OOP advice, "program to an interface".
This strategy takes advantage of Python's polymorphism or duck-typing.
So just attempt to access the interface, catching the specific expected errors (AttributeError
in case there is no .items
and TypeError
in case items
is not callable) with a reasonable fallback - and now any class that implements that interface will give you its items (note .iteritems()
is gone in Python 3):
try:
items = any_object.items()
except (AttributeError, TypeError):
non_items_behavior(any_object)
else: # no exception raised
for item in items: ...
Perhaps you might think using duck-typing like this goes too far in allowing for too many false positives, and it may be, depending on your objectives for this code.
Don't use is
to check types for standard control flow. Use isinstance
, consider abstractions like Mapping
or MutableMapping
, and consider avoiding type-checking altogether, using the interface directly.