Difference between type(obj) and obj.__class__ Difference between type(obj) and obj.__class__ python python

Difference between type(obj) and obj.__class__


This is an old question, but none of the answers seems to mention that. in the general case, it IS possible for a new-style class to have different values for type(instance) and instance.__class__:

class ClassA(object):    def display(self):        print("ClassA")class ClassB(object):    __class__ = ClassA    def display(self):        print("ClassB")instance = ClassB()print(type(instance))print(instance.__class__)instance.display()

Output:

<class '__main__.ClassB'><class '__main__.ClassA'>ClassB

The reason is that ClassB is overriding the __class__ descriptor, however the internal type field in the object is not changed. type(instance) reads directly from that type field, so it returns the correct value, whereas instance.__class__ refers to the new descriptor replacing the original descriptor provided by Python, which reads the internal type field. Instead of reading that internal type field, it returns a hardcoded value.


Old-style classes are the problem, sigh:

>>> class old: pass... >>> x=old()>>> type(x)<type 'instance'>>>> x.__class__<class __main__.old at 0x6a150>>>> 

Not a problem in Python 3 since all classes are new-style now;-).

In Python 2, a class is new-style only if it inherits from another new-style class (including object and the various built-in types such as dict, list, set, ...) or implicitly or explicitly sets __metaclass__ to type.


type(obj) and type.__class__ do not behave the same for old style classes:

>>> class a(object):...     pass...>>> class b(a):...     pass...>>> class c:...     pass...>>> ai=a()>>> bi=b()>>> ci=c()>>> type(ai) is ai.__class__True>>> type(bi) is bi.__class__True>>> type(ci) is ci.__class__False