When is the type (instance) not an instance of .__ class__?

Python has a built-in type function, and each instance also has __class__ . I generally believed that they returned the same. Even the documentation for both sounds is similar:

instance.__class__

The class to which the class instance belongs.

and

type(object)

Use one argument to return the type of the object.

However, in abc.ABCMeta.__instancecheck__ there is a check if they are identical (slightly reduced):

 subclass = instance.__class__ subtype = type(instance) if subtype is subclass: 

When will it be wrong? When does type(instance) not match instance.__class__ ?

+7
source share
2 answers

type(instance) and instance.__class__ may be different, even with new-style classes , as Guido mentioned in PEP 3119 :

In addition, isinstance(x, B) equivalent to issubclass(x.__class__, B) or issubclass(type(x), B) . (Perhaps type(x) and x.__class__ are not x.__class__ and the same object, for example, when x is a proxy object.)

For instance:

 class A: pass class B: __class__ = A b = B() print(type(b)) # prints <class '__main__.B'> print(b.__class__) # prints <class '__main__.A'> 
+3
source

This applies to old-style objects (inheriting from nothing). Such objects do not have the __class__ property. I think they do it in such a way as to prevent mistakes. Example for Python 2.7:

 class A: pass class B(object): pass a = A() b = B() print(dir(a)) # ['__doc__', '__module__'] print(dir(b)) # ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__'] print(b.__class__) # <class '__main__.B'> print(type(b)) # <class '__main__.B'> ##################### # The intersting part print(a.__class__) # __main__.A print(type(a)) # <type 'instance'> print(B.__class__) # <type 'type'> print(type(B)) # <type 'type'> print(type(A)) # <type 'classobj'> #print(A.__class__) # AttributeError: class A has no attribute '__class__' 

See additional information:

Note: These lines from cpython were last modified in 2008 ( commit ), so it really looks like compatibility, or they just forgot about it.

+2
source

Source: https://habr.com/ru/post/1015171/


All Articles