Determine if Python variable is an instance of a built-in type
I need to determine if a given Python variable is an instance of native type: str , int , float , bool , list , dict and so on. Is there elegant way to doing it? Or is this the only way:
if myvar in (str, int, float, bool): # do something
What do you mean by «native» type? Do you mean builtin? Why do you need to know this? Python isn’t C++ or Java, so there’s no distinction between «simple» or «native» types. What are you trying to do?
Yes, I guess I mean «builtin» types. I need such representation of an object, that I could use it in JSON serialization. simplejson «handles» only such types. In other cases (when object are instances of «homemade» classes) i need to make dict objects.
Yes, But as I understood this — I should write such decoder for each kind of class I want to serialize. I don’t want to do it.
@Aleksandr Motsjonov: Please update your question to specifically say that you’re interested in types that simplejson handles by default.
11 Answers 11
This is an old question but it seems none of the answers actually answer the specific question: «(How-to) Determine if Python variable is an instance of a built-in type». Note that it’s not «[. ] of a specific/given built-in type» but of a.
The proper way to determine if a given object is an instance of a buil-in type/class is to check if the type of the object happens to be defined in the module __builtin__ .
def is_builtin_class_instance(obj): return obj.__class__.__module__ == '__builtin__'
Warning: if obj is a class and not an instance, no matter if that class is built-in or not, True will be returned since a class is also an object, an instance of type (i.e. AnyClass.__class__ is type ).
@glarrain how would you modify this to handle the general case you mention in which obj is a class not an instance?
@jtlz2 you can store the name in a variable and compare it with that variable, like builtin_module_name=dict().__class__.__module__
The best way to achieve this is to collect the types in a list of tuple called primitiveTypes and:
if isinstance(myvar, primitiveTypes): .
The types module contains collections of all important types which can help to build the list/tuple.
using types from ‘types’ is no different than using the more straightforward names (int, str, float, . ) directly!
Yes, that’s how types works. But it makes your intention more clean and if you use the predefined sets (StringTypes), you get additional portability between Python versions.
Note that the types module does not really provide a complete list of types. For example there’s no int there. However there’s the buildins module that provides most built-ins, so one can do builtin_types = tuple(getattr(builtins, t) for t in dir(builtins) if isinstance(getattr(builtins, t), type)) and then use isinstance(value, builtin_types) .
isinstance is true for subclasses of builtin types, whereas type(value) in (bool, str, int, float, tuple, list, dict) is true only for instances of the builtin types. This difference is pointed out in this answer: stackoverflow.com/a/6392016/1959808
Not that I know why you would want to do it, as there isn’t any «simple» types in Python, it’s all objects. But this works:
type(theobject).__name__ in dir(__builtins__)
But explicitly listing the types is probably better as it’s clearer. Or even better: Changing the application so you don’t need to know the difference.
Update: The problem that needs solving is how to make a serializer for objects, even those built-in. The best way to do this is not to make a big phat serializer that treats builtins differently, but to look up serializers based on type.
def IntSerializer(theint): return str(theint) def StringSerializer(thestring): return repr(thestring) def MyOwnSerializer(value): return "whatever" serializers = < int: IntSerializer, str: StringSerializer, mymodel.myclass: MyOwnSerializer, >def serialize(ob): try: return ob.serialize() #For objects that know they need to be serialized except AttributeError: # Look up the serializer amongst the serializer based on type. # Default to using "repr" (works for most builtins). return serializers.get(type(ob), repr)(ob)
This way you can easily add new serializers, and the code is easy to maintain and clear, as each type has its own serializer. Notice how the fact that some types are builtin became completely irrelevant. 🙂
How to check if a variable is a dictionary in Python?
How would you check if a variable is a dictionary in Python? For example, I’d like it to loop through the values in the dictionary until it finds a dictionary. Then, loop through the one it finds:
dict = > for k, v in dict.iteritems(): if ###check if v is a dictionary: for k, v in v.iteritems(): print(k, ' ', v) else: print(k, ' ', v)
No, it is not the same question. The answer to this question and to the other questions listed here all contain substantially the same information. But the answer to «How to check if a variable is a dictionary in python» is «Use type() or isinstance()» which then leads to a new question, which is what is the difference between type() and isinstance(). But the person asking the first question can’t possibly know that until the first question is answered. Ergo, different questions, which matters when you are looking for your question on the site.
I agree with @mbakeranalecta I came here looking for the answer to the question «How to check is a variable is a dictionary in Python?» and I would have never thought to look my answer into «Differences between isinstance() and type() in python».
For checking if a variable is a dictionary in particular, you should probably use isinstance(v, collections.abc.Mapping) . In other words, this is not an exact duplicate of «Differences between isinstance() and type().»
5 Answers 5
You could use if type(ele) is dict or use isinstance(ele, dict) which would work if you had subclassed dict :
d = > for element in d.values(): if isinstance(element, dict): for k, v in element.items(): print(k,' ',v)
I down-voted this answer because the right answer to the general question is: isinstance(ele, collections.Mapping) . It works for dict() , collections.OrderedDict() , and collections.UserDict() . The example in the question is specific enough for Padriac’s answer to work, but it’s not good enough for the general case.
I downvoted this answer because if you are going to to invoke ele.items() why are you checking type? EAFP/duck-typing works here, just wrap for k,v in ele.items() in try. except (AttributeError, TypeError) . If exception is raised, you know ele has no items that yields an iterable.
@Padraic Cunningham Your hypothetical edge case would require that your «100% not a dict» custom class 1. had an items() method 2. which just so happened to yield an iterable and 3. where each element of that iterable can be represented as a 2-tuple. At this point your custom object has already implemented half of a dict already. For the purposes of the code listed we only cared about conditional expansion of the nested element, and your custom object already implements that. (It’s a bit ironic that you criticize @Alexander Ryzhov’s comment for being too general but now raise a general case)
@PadraicCunningham I’d rather not teach people-who-are-not-overly-familiar-with-Python anti-patterns to begin with. There are very few use-cases in Python that require explicit typechecking — most stem from inheriting a bad implementation to begin with (‘god object’s, overriding standard library/language constructs, etc.) The original question is itself an XY problem. Why does the OP need to check type? Because according to their code what they really want to do is to check whether an item in their collection behaves like a collection (implements items() that yields a nested iterable).
@AlexanderRyzhov Why not post that approach as an answer? BTW as Josh Kelley has commented above suggesting collections.abc.Mapping , a note might be appropriate that they’re the same, but collections.abc is not available before Python 3.3. collections.Mapping alias is still available in Python 3.6, but not documented, so probably one should prefer collections.abc.Maping .
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.
Supporting inheritance:
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.
Supporting abstractions:
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.
Use the interface
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.
Conclusion
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.