What is the best (idiomatic) way to check the type of a Python variable?

The Question :

319 people think this question is useful

I need to know if a variable in Python is a string or a dict. Is there anything wrong with the following code?

if type(x) == type(str()):
elif type(x) == type(dict()):
    raise ValueError

Update: I accepted avisser’s answer (though I will change my mind if someone explains why isinstance is preferred over type(x) is).

But thanks to nakedfanatic for reminding me that it’s often cleaner to use a dict (as a case statement) than an if/elif/else series.

Let me elaborate on my use case. If a variable is a string, I need to put it in a list. If it’s a dict, I need a list of the unique values. Here’s what I came up with:

def value_list(x):
    cases = {str: lambda t: [t],
             dict: lambda t: list(set(t.values()))}
        return cases[type(x)](x)
    except KeyError:
        return None

If isinstance is preferred, how would you write this value_list() function?

The Question Comments :
  • IMHO, isinstance() is better because you test the type of certain variable against a certain class type, without having to allocate/create anything. I mean: when you do type(str()), you are creating an instance of a str object just for the sake of obtaining its type. The object just created is then discarded and later garbage collected. You don’t need anything like this because the type you are testing against is known in advance, so, it is more efficient if you do isinstance(variable, type).
  • @RichardGomes Actually, you confuse two different topics. If the goal is to avoid allocating a str, then the coder should simply say str instead of type(str()). Assuming the coder meant what they said, which is to test for an EXACT type. The point of isinstance is to allow subtypes. Which may or may not have been wanted. E.g. collections.OrderedDict is a subclass of dict, so IF the coder wants to allow those also, THEN it is correct to change the code from type(x) == dict to isinstance(x, dict). NOT to avoid allocating, BUT to change the meaning to “a subclass is acceptable”.
  • Allocating something empty and checking with type() is improper not just because of the useless object’s instance, but even because you can’t check, for example, if your object is a file without creating a file on filesystem (type(file()) fails because file() requires at least an argument)

The Answer 1

333 people think this answer is useful

What happens if somebody passes a unicode string to your function? Or a class derived from dict? Or a class implementing a dict-like interface? Following code covers first two cases. If you are using Python 2.6 you might want to use collections.Mapping instead of dict as per the ABC PEP.

def value_list(x):
    if isinstance(x, dict):
        return list(set(x.values()))
    elif isinstance(x, basestring):
        return [x]
        return None

The Answer 2

61 people think this answer is useful

type(dict()) says “make a new dict, and then find out what its type is”. It’s quicker to say just dict. But if you want to just check type, a more idiomatic way is isinstance(x, dict).

Note, that isinstance also includes subclasses (thanks Dustin):

class D(dict):

d = D()
print("type(d) is dict", type(d) is dict)  # -> False
print("isinstance (d, dict)", isinstance(d, dict))  # -> True

The Answer 3

40 people think this answer is useful

built-in types in Python have built in names:

>>> s = "hallo"
>>> type(s) is str
>>> s = {}
>>> type(s) is dict

btw note the is operator. However, type checking (if you want to call it that) is usually done by wrapping a type-specific test in a try-except clause, as it’s not so much the type of the variable that’s important, but whether you can do a certain something with it or not.

The Answer 4

22 people think this answer is useful

isinstance is preferrable over type because it also evaluates as True when you compare an object instance with it’s superclass, which basically means you won’t ever have to special-case your old code for using it with dict or str subclasses.

For example:

 >>> class a_dict(dict):
 ...     pass
 >>> type(a_dict()) == type(dict())
 >>> isinstance(a_dict(), dict)

Of course, there might be situations where you wouldn’t want this behavior, but those are –hopefully– a lot less common than situations where you do want it.

The Answer 5

8 people think this answer is useful

I think I will go for the duck typing approach – “if it walks like a duck, it quacks like a duck, its a duck”. This way you will need not worry about if the string is a unicode or ascii.

Here is what I will do:

In [53]: s='somestring'

In [54]: u=u'someunicodestring'

In [55]: d={}

In [56]: for each in s,u,d:
    if hasattr(each, 'keys'):
        print list(set(each.values()))
    elif hasattr(each, 'lower'):
        print [each]
        print "error"

The experts here are welcome to comment on this type of usage of ducktyping, I have been using it but got introduced to the exact concept behind it lately and am very excited about it. So I would like to know if thats an overkill to do.

The Answer 6

7 people think this answer is useful

I think it might be preferred to actually do

if isinstance(x, str):
elif isinstance(x, dict):
    raise ValueError

2 Alternate forms, depending on your code one or the other is probably considered better than that even. One is to not look before you leap

  one, two = tupleOrValue
except TypeError:
  one = tupleOrValue
  two = None

The other approach is from Guido and is a form of function overloading which leaves your code more open ended.


The Answer 7

3 people think this answer is useful

That should work – so no, there is nothing wrong with your code. However, it could also be done with a dict:

{type(str()): do_something_with_a_string,
 type(dict()): do_something_with_a_dict}.get(type(x), errorhandler)()

A bit more concise and pythonic wouldn’t you say?

Edit.. Heeding Avisser’s advice, the code also works like this, and looks nicer:

{str: do_something_with_a_string,
 dict: do_something_with_a_dict}.get(type(x), errorhandler)()

The Answer 8

3 people think this answer is useful

You may want to check out typecheck. http://pypi.python.org/pypi/typecheck

Type-checking module for Python

This package provides powerful run-time typechecking facilities for Python functions, methods and generators. Without requiring a custom preprocessor or alterations to the language, the typecheck package allows programmers and quality assurance engineers to make precise assertions about the input to, and output from, their code.

The Answer 9

1 people think this answer is useful

I’ve been using a different approach:

from inspect import getmro
if (type([]) in getmro(obj.__class__)):
    # This is a list, or a subclass of...
elif (type{}) in getmro(obj.__class__)):
    # This one is a dict, or ...

I can’t remember why I used this instead of isinstance, though…

The Answer 10

-3 people think this answer is useful


No, typechecking arguments in python is not necessary. It is never necessary.

If your code accepts either a string or a dict object, your design is broken.

That comes from the fact that if you don’t know already the type of an object in your own program, then you’re doing something wrong already.

Typechecking hurts code reuse and reduces performance. Having a function that performs different things depending on the type of the object passed is bug-prone and has a behavior harder to understand and maintain.

You have the following saner options:

1) Make a function unique_values that converts dicts in unique lists of values:

def unique_values(some_dict):
    return list(set(some_dict.values()))

Make your function assume the argument passed is always a list. That way, if you need to pass a string to the function, you just do:


If you need to pass it a dict, you do:


That’s your best option, it is clean, easy to understand and maintain. Anyone reading the code immediatelly understands what is happening, and you don’t have to typecheck.

2) Make two functions, one that accepts lists of strings and one that accepts dicts. You can make one call the other internally, in the most convenient way (myfunction_dict can create a list of strings and call myfunction_list).

In any case, don’t typecheck. It is completely unnecessary and has only downsides. Refactor your code instead in a way you don’t need to typecheck. You only get benefits in doing so, both in short and long run.

Add a Comment