Python type() or __class__, == or is
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__()
.
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): passclass Bar(Foo): pass>>> obj = Bar()>>> isinstance(obj, Foo)True>>> type(obj) == FooFalse
The OP wants the behavior of type(obj) == Foo
, where it will be false even though Foo
is a base class of Bar
.
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.