41

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
icedwater
  • 4,701
  • 3
  • 35
  • 50
Aleksandr Motsjonov
  • 1,230
  • 3
  • 14
  • 25
  • 6
    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? – S.Lott Aug 24 '09 at 12:30
  • 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. – Aleksandr Motsjonov Aug 24 '09 at 12:43
  • 1
    You know that simplejson has something called "object decoding" and "object encoding"? –  Aug 24 '09 at 12:46
  • 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 Aug 24 '09 at 12:50
  • @Aleksandr Motsjonov: Please update your question to specifically say that you're interested in types that simplejson handles by default. – S.Lott Aug 24 '09 at 13:06
  • @Aleksandr Motsjonov: Even when you need one decoder per type, it's irrelevant if that type is builtin or not. I updated my answer to reflect your actual problem. – Lennart Regebro Aug 24 '09 at 13:19
  • you should really look at S.Lott's answer 'cause it's better than the one you picked... I added some code to show how it would actually be used, but you really shouldn't care if something is a builtin or not, instead you should see if what you are trying to do is supported, and otherwise try something else – Terence Honles Aug 24 '09 at 23:04

11 Answers11

32

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
  • 8,031
  • 7
  • 31
  • 44
12

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.

Something like this:

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. :)

Lennart Regebro
  • 167,292
  • 41
  • 224
  • 251
  • +1 "Changing the application so you don't need to know the difference." Some (extremely rare) times is necesary to know, but most likely isn't. – Esteban Küber Aug 24 '09 at 12:44
12

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.

Works since Python 2.2

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
  • 2
    using types from 'types' is no different than using the more straightforward names (int, str, float, ...) directly! – u0b34a0f6ae Aug 24 '09 at 13:07
  • 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. – Aaron Digulla Aug 24 '09 at 13:37
  • It's also slightly faster ... ;) – Aaron Digulla Aug 24 '09 at 13:38
  • I'm not sure this is the best approach. Basically you import types from the `types` modules and check against them, but the docs discourages this way since python 2.2 on. Accordingly to the docs using `isinstance` is preferred. [The 2nd code example shows a simple case](http://docs.python.org/2/library/types.html). – Paolo Nov 18 '12 at 13:01
  • @Guandalino: Thanks, improved my answer. – Aaron Digulla Nov 19 '12 at 10:42
  • 3
    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)`. – Bakuriu Jun 10 '16 at 10:54
  • "..dict and so on.": Suddenly isinstance(NamedTuple, tuple) == true. Class name/builtins should be also checked. – Denis Barmenkov Apr 15 '20 at 01:24
  • 1
    `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: https://stackoverflow.com/a/6392016/1959808 – 0 _ Apr 20 '20 at 01:45
7

You appear to be interested in assuring the simplejson will handle your types. This is done trivially by

try:
    json.dumps( object )
except TypeError:
    print "Can't convert", object

Which is more reliable than trying to guess which types your JSON implementation handles.

S.Lott
  • 384,516
  • 81
  • 508
  • 779
  • this is more pythonic 'cause if the object can be dumped (say perhaps simplejson adds more support) then it will be used first, and then in the except you should call your catchall functionality. +1 – Terence Honles Aug 24 '09 at 22:28
  • What if the object is a huge dict? wouldn't it be a waist of resources? – ניר May 20 '22 at 07:52
2

What is a "native type" in Python? Please don't base your code on types, use Duck Typing.

1

you can access all these types by types module:

`builtin_types = [ i for i in  types.__dict__.values() if isinstance(i, type)]`

as a reminder, import module types first

def isBuiltinTypes(var):
    return type(var) in types.__dict__.values() and not isinstance(var, types.InstanceType)
wizzwizz4
  • 6,140
  • 2
  • 26
  • 62
jacoolee
  • 153
  • 1
  • 3
1

For me the best option is:

allowed_modules = set(['numpy'])
def isprimitive(value):
  return not hasattr(value, '__dict__') or \
  value.__class__.__module__ in allowed_modules

This fix when value is a module and value.__class__.__module__ == '__builtin__' will fail.

asterio gonzalez
  • 1,056
  • 12
  • 12
1

It's 2020, I'm on python 3.7, and none of the existing answers worked for me. What worked instead is the builtins module. Here's how:

import builtins
type(your_object).__name__ in dir(builtins)
ifedapo olarewaju
  • 3,031
  • 1
  • 21
  • 25
0

building off of S.Lott's answer you should have something like this:


from simplejson import JSONEncoder

class JSONEncodeAll(JSONEncoder):
  def default(self, obj):
    try:
      return JSONEncoder.default(self, obj)
    except TypeError:
      ## optionally
      # try:
      #   # you'd have to add this per object, but if an object wants to do something
      #   # special then it can do whatever it wants
      #   return obj.__json__()
      # except AttributeError:
      ##

      # ...do whatever you are doing now...
      # (which should be creating an object simplejson understands)

to use:


>>> json = JSONEncodeAll()

>>> json.encode(myObject)
# whatever myObject looks like when it passes through your serialization code

these calls will use your special class and if simplejson can take care of the object it will. Otherwise your catchall functionality will be triggered, and possibly (depending if you use the optional part) an object can define it's own serialization

Terence Honles
  • 834
  • 6
  • 9
0

The question asks to check for non-class types. These types don't have a __dict__ member (You could also test for __repr__ member, instead of checking for __dict__) Other answers mention to check for membership in types.__dict__.values(), but some of the types in this list are classes.

def isnonclasstype(val):
    return getattr(val,"__dict__", None) != None

a=2
print( isnonclasstype(a) )

a="aaa"
print( isnonclasstype(a) )

a=[1,2,3]
print( isnonclasstype(a) )

a={ "1": 1, "2" : 2 }
print( isnonclasstype(a) )

class Foo:
    def __init__(self):
        pass

a = Foo()
print( isnonclasstype(a) )

gives me:

> python3 t.py
False
False
False
False
True
> python t.py
False
False
False
False
True
MichaelMoser
  • 3,172
  • 1
  • 26
  • 26
-1

Built in type function may be helpful:

>>> a = 5
>>> type(a)
<type 'int'>
balpha
  • 50,022
  • 18
  • 110
  • 131
kolistivra
  • 4,229
  • 9
  • 45
  • 58