Python type() or __class__, == or is

Solution 1:

For old-style classes, there is a difference:

>>> class X: pass
... 
>>> type(X)
<type 'classobj'>
>>> X.__class__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: class X has no attribute '__class__'
>>> x = X()
>>> x.__class__
<class __main__.X at 0x171b5d50>
>>> type(x)
<type 'instance'>

The point of new-style classes was to unify class and type. Technically speaking, __class__ is the only solution that will work both for new and old-style class instances, but it will also throw an exception on old-style class objects themselves. You can call type() on any object, but not every object has __class__. Also, you can muck with __class__ in a way you can't muck with type().

>>> class Z(object):
...     def __getattribute__(self, name):
...             return "ham"
... 
>>> z = Z()
>>> z.__class__
'ham'
>>> type(z)
<class '__main__.Z'>

Personally, I usually have an environment with new-style classes only, and as a matter of style prefer to use type() as I generally prefer built-in functions when they exist to using magic attributes. For example, I would also prefer bool(x) to x.__nonzero__().

Solution 2:

The result of type() is equivalent to obj.__class__ in new style classes, and class objects are not safe for comparison using is, use == instead.

For new style classes the preferable way here would be type(obj) == Foo.

As Michael Hoffman pointed out in his answer, there is a difference here between new and old style classes, so for backwards compatible code you may need to use obj.__class__ == Foo.

For those claiming that isinstance(obj, Foo) is preferable, consider the following scenario:

class Foo(object):
    pass

class Bar(Foo):
    pass

>>> obj = Bar()
>>> isinstance(obj, Foo)
True
>>> type(obj) == Foo
False

The OP wants the behavior of type(obj) == Foo, where it will be false even though Foo is a base class of Bar.

Solution 3:

is should only be used for identity checks, not type checks (there is an exception to the rule where you can and should use is for check against singletons).

Note: I would generally not use type and == for type checks, either. The preferable way for type checks is isinstance(obj, Foo). If you ever have a reason to check if something is not an subclass instance, it smells like a fishy design to me. When class Foo(Bar):, then Bar is a Foo, and you should be avoiding any situations where some part of your code has to work on a Foo instance but breaks on a Bar instance.