A detailed analysis of the differences between new classes and classical classes in Python

  • 2021-07-13 05:37:34
  • OfStack

1. New classes and classical classes

In Python 2 and previous versions, classes derived from any built-in type (as long as one built-in type is located somewhere in the class tree) are all "new classes" and will get all the characteristics of "new classes"; Conversely, classes that are not derived from any built-in type are called "classic classes".

The distinction between "new class" and "classic class" no longer exists after Python 3, and after Python 3. x, because all classes are derived from the built-in type object (even if the inherited object type is not shown), that is, all classes are "new classes".

Official document https://www.python.org/doc/newstyle/

2. Differences in succession order

This problem is mainly encountered when multiple inheritance occurs.

Classic DIA inheritance is depth first, that is, searching from bottom to top; The inheritance order of the new class is C3 algorithm (non-breadth first).

Code validation for classic classes (all code for classic classes must run under Python2, the same below), ClassicClassB inherits from ClassicClassA, SubClassicClass inherits from ClassicClassB, ClassicClassC:


class ClassicClassA():
 var = 'Classic Class A'


class ClassicClassB(ClassicClassA):
 pass


class ClassicClassC():
 var = 'Classic Class C'


class SubClassicClass(ClassicClassB, ClassicClassC):
 pass


if __name__ == '__main__':
 print(SubClassicClass.var)

In the process of searching for var attribute by SubClassicClass, according to the principle from bottom to top, ClassicClassB will be searched first, while ClassicClassB does not have var attribute, so it will continue to search for ClassicClassA superclass of ClassicClassB, and stop searching after finding var attribute in ClassicClassA, and the value of var is the value of var in ClassicClassA; The var attribute of ClassicClassC was not searched from beginning to end.

From the running results, we can see that the output is Classic Class A, which shows that the search of class inheritance is depth first and searches from bottom to top.

Classic Class A

The inheritance order of the new class is not breadth-first, but C3 algorithm, but in some cases, the result of C3 algorithm happens to be the same as breadth-first algorithm.

Code validate the inheritance search order of the new class. In the new class, you can use the mro function to view the search order of the class (this is also a difference), such as SubNewStyleClass. mro ().


class NewStyleClassA(object):
 var = 'New Style Class A'


class NewStyleClassB(NewStyleClassA):
 pass


class NewStyleClassC(NewStyleClassA):
 var = 'New Style Class C'


class SubNewStyleClass(NewStyleClassB, NewStyleClassC):
 pass


if __name__ == '__main__':
 print(SubNewStyleClass.mro())
 print(SubNewStyleClass.var)

From the code running results, it happens to be the same as the breadth-first expected results from left to right.

[ < class '__main__.SubNewStyleClass' > , < class '__main__.NewStyleClassB' > , < class '__main__.NewStyleClassC' > , < class '__main__.NewStyleClassA' > , < type 'object' > ]
New Style Class C

However, it does not mean that the inheritance order of the new class is breadth-first. You can modify the code slightly to verify it: NewStyleClassC inherits from object instead


class NewStyleClassA(object):
 var = 'New Style Class A'


class NewStyleClassB(NewStyleClassA):
 pass


class NewStyleClassC(object):
 var = 'New Style Class C'


class SubNewStyleClass(NewStyleClassB, NewStyleClassC):
 pass


if __name__ == '__main__':
 print(SubNewStyleClass.mro())
 print(SubNewStyleClass.var)

Run results no longer meet breadth first:

[ < class '__main__.SubNewStyleClass' > , < class '__main__.NewStyleClassB' > , < class '__main__.NewStyleClassA' > , < class '__main__.NewStyleClassC' > , < type 'object' > ]
New Style Class A

It can be seen that the inheritance order of the new class is not breadth first, but C3 algorithm. As for C3 algorithm, we will write it in detail later.

3. Differences in class instance types

In classic classes, all classes are of type classobj, and instances of classes are of type instance. Classes are associated with instances only through the __class__ attribute. This makes it inconvenient to determine the instance type: All instances are instance type.


class A():pass
class B():pass

a = A()
b = B()

if __name__ == '__main__':
 print(type(a))
 print(type(b))
 print(type(a) == type(b))

type (a) = = The result of type (b) is always True, so this comparison is meaningless.

Even more troublesome is that the instance of the classic class is instance type, while the instance of the built-in class is not, so it is impossible to unify 1.

Determine by code what type is the instance [1, 2, 3] of the built-in type list


print(type([1, 2, 3]))

Run result, list type

< type 'list' >

The instance type of built-in class is completely different from that of classic class, which is easy to cause confusion and is not conducive to the unification of code.

This problem no longer exists after Python 3, because all classes in Python 3 are new classes, in which classes and types have been unified: the type of a class instance is the class from which it was created (usually the same as the __class__ of the class instance), instead of the "instance" instance type in Python 2. x version.

More detailed: https://www.ofstack.com/article/165048. htm

Summarize


Related articles: