5

How do I determine if a "variable" is builtin like string, list, dict or number and not an "object". I am trying to do a deepcopy-ish function for dicts which copies builtin types but ignores objects.

Prof. Falken
  • 24,226
  • 19
  • 100
  • 173
  • 2
    Everything in python is an object. You could use type(object) to determine the type of the object. – Ankur Ankan Jun 12 '13 at 07:11
  • @AnkurAnkan the question is asking how to check for a buil-in, not for a pre determined type – jamylak Jun 12 '13 at 07:14
  • @jamylak I believe @Ankur Ankan was just leading up to the use of `type(object)`. – icedwater Jun 12 '13 at 07:34
  • 1
    Note that 99% of the time, you *don't* want to type-check. In Python, duck typing is the standard, so just use things, and catch exceptions if they fail. Never using type-checking to check for capability, as you will exclude types that act like another. – Gareth Latty Jun 12 '13 at 08:48
  • @Lattyware, I know, but in this case I saw no other simple way to do it. I have a dict I want to log in a database, but I am only interesting in things which can be JSON encoded as plain text. I have in the same dict some callbacks and stuff which I don't want to serialize. I don't want to remove them by name with `del`, because I don't want to modify the original `dict'. – Prof. Falken Jun 12 '13 at 09:11
  • @Prof.Falken Why not make your own [`JSONEncoder`](http://docs.python.org/3.3/library/json.html#json.JSONEncoder) subclass that ignores anything that can't be handled normally? – Gareth Latty Jun 12 '13 at 09:18

8 Answers8

3

Everything is an object. If you want to figure out if a certain object is a string or an integer, or another type, use isinstance():

>>> isinstance("hello!", str)
True
>>> isinstance("hello!", int)
False

So, in your case, it seems you want to call a function only with dictionaries:

>>> mylist = [3, "cabbage", 5.43, {'cat':'dog'}, {'horse':'elephant'}, ['another', 'list']]
>>> for i in mylist:
...     if isinstance(i, dict):
...         dostuff()
TerryA
  • 58,805
  • 11
  • 114
  • 143
2

Since there are few built-in types, you can check using if:

if type(a)==int or type(a)==float or type(a)==str or type(a)==list or type(a)==dict:
        #do something

or use isinstance()

if isinstance(a,(int,float,str,list,dict,set)):
    #do something

Don't know if this is the correct way to do it. But it is one of the ways to check if the given variable is an instance of any built-in data type

Aswin Murugesh
  • 10,831
  • 10
  • 40
  • 69
1

I think using the class.__module__ attribute, which holds the module name where the class was defined, is the best way to go:

>>> import __builtin__
>>> int.__module__ == __builtin__.__name__
True

Notice that although the builtin module is automatically imported, we have to import it to bring it in scope and fetch its name.

For a user defined class:

>>> class A: pass
...
>>> A.__module__
'__main__'
icecrime
  • 74,451
  • 13
  • 99
  • 111
1

First of all everything is object, so I suppose you want to test for built-in types versus user defined types.

Pick the built-in's that you want to exclude and compare type() of the variable.

if type(yourvar) in [list,set,int,float,str,dict]:
    print "builtin"
else:
    print "object"

In general isinstance is preferred to comparing type. However isinstance will be True for objects that extend built-in types:

>>> class A(list):
    pass

>>> a = A()
>>> isinstance(a,list)
True

Therefore if you want strictly built-in types, you shouldn't use isinstance.

jujaro
  • 447
  • 2
  • 4
  • Don't forget about bool! I was using this, and I needed to add that for my code to work. :) – Max May 04 '22 at 03:49
0

CPython only approach (may work in other implementations as well):

import __builtin__

builtin_types = [x for x in __builtin__.__dict__.values() if isinstance(x, type)]
def is_builtin_type(x):
  for t in builtin_types:
    if isinstance(x, t):
       return True 

This covers built-in exceptions, bytearrays, objects, and couple others, that guys on other answers did not mention :-)

Michał Fita
  • 1,183
  • 1
  • 7
  • 24
0

First of all, in Python there is no difference between classes and types:

>>> type("234"), "234".__class__
(str, str)

Then testing a type for an objects can have two different meanings:

isinstance tests if your object is of a given type or a subtype:

>>> class mystr(str): pass
>>> s = mystr(4)
>>> s
'4'
>>> ype(s)
__main__.mystr
>>> isinstance(s, str)
True

whereas

>>> type(s) is str
False
>>> type(s)
<class '__main__.mystr'>

by the way you shouldn't write type(s) == str but type(s) is str.

Now a possible answer to your question: the module of a builtin type is __builtin__

>>> str.__module__
'__builtin__'
>>> mystr.__module__
'__main__'

So you probably can write

>>> def is_of_builtin_type(obj):
        return type(obj).__module__ == '__builtin__'
>>> is_of_builtin_type("4223")
True
>>> class mystr(str): pass
>>> is_of_builtin_type(mystr(223))
False

Note: I haven't tested how robust this is.

hivert
  • 10,579
  • 3
  • 31
  • 56
0

FYI, I went with this solution: (inspired by this)

from six import integer_types, string_types, text_type

_copyable_types = (
    integer_types,
    string_types,
    text_type,
    list,
    dict,
    set,
)


def deepish_copy(org):
    '''
    Will copy a dict but ignore user objects at top level.
    '''
    out = {}

    for k, v in org.iteritems():
        if isinstance(v, _copyable_types):
            try:
                out[k] = v.copy()   # dicts, sets
            except AttributeError:
                try:
                    out[k] = v[:]   # lists, tuples, strings, unicode
                except TypeError:
                    out[k] = v      # ints

    return out
Prof. Falken
  • 24,226
  • 19
  • 100
  • 173
-2

Straightforward

For a given variable var, using the function isinstance(var, type) returns True if var is of type type and False otherwise. You can check this easily in the interpreter:

>>> a = 2
>>> isinstance(a, int)
True
>>> b = 'correct'
>>> isinstance(b, int)
False
>>> c = [1,2,3,4]
>>> isinstance(c, list)
True

...and so on. So if you want to check that item is a dict:

if isinstance(item, dict):
    # handle the dict, do your deep copy
else:
    # meh, whatever

Alternatively

Consider using the types module which allows:

from types import DictType
def dictate(item):
    if isinstance(item, dict):
       # handle the dict
    else:
       # panic!
icedwater
  • 4,701
  • 3
  • 35
  • 50