This is my fourth day of the Gwen Challenge
Background, this is all about inheritance, which is something we need to think about when we use inheritance, especially when we use super().
It’s worth noting that Python3 and Python2 parse methods in a different order, and python2 is a pariah of the time, so I’m not going to explain it here, but I’m going to focus on the order in which Python3 parse methods.
Python’s method parsing order is based on C3, which is a compilation of the Dylan programming language.A custom class is a type that is typically created through a class definition(See the class Definition section.) Each class has a separate namespace implemented through a dictionary object. Class attribute references are converted to look up in this dictionary, for example C.x is converted to C.dict[“x”] (although some hook objects exist in ways that allow other positioning properties). When an attribute name is not found in it, the search continues in the base class. This base-class lookup uses the C3 method to resolve the order and maintains correct behavior even in the presence of a ‘diamond’ inheritance structure, where multiple inheritance paths connect to a common ancestor. Details on the C3 MRO used by Python can be found in the documentation accompanying the 2.3 releasewww.python.org/download/re….
The official explanation is here
An example diagram of the diamond-shaped structure above:
Code examples:
class CommonBase:
def method(self) :
print('CommonBase')
class Base1(CommonBase) :
pass
class Base2(CommonBase) :
def method(self) :
print('Base2')
class MyClass(Base1,Base2) :
pass
MyClass().method()
=====> Base2
Copy the code
If you’re in python2, you’ll get CommonBase. As you know, super inheritance is the way multiple inheritance works in this example, so knowing the order of method resolution in python3 will help you a lot when you’re using super.
Python3 built-in __mro__
Python3 shows us the shortest path for modern programming languages, so how does it work?
Python3 MRO actually makes recursive calls to base classes:
L[MyClass(Base1,Base2)] = merge(L[Base1],L[Base2],Base1,Base2) Merge is a concrete algorithm that merges multiple linearized results and the linearization of C is the sum of C plus the linearization of the parent class and the merging of the parent class list.Copy the code
This may sound like a mouthful, but it actually happens by taking the first element of the list (head is the first element of the list, and tail contains the rest). For example, in (Base1,Base2… ,BaseN), Base1 is head, and (Base2… ,BaseN) is tail), or L[Base1][0]. If the header is not at the tail of any other list, it is added to Myclass linearization and removed from the merge list; Otherwise, look at the header for the next list and pull it out if it’s a good one. This process is then repeated until all classes are removed or no good headers can be found. In the latter case, the merge cannot be built, and Python 3 will refuse to create the MyClass class and throw an exception.
That is, C3 performs a recursive deep search on each parent class to get a list sequence. Then, if a class is contained in multiple lists, it uses hierarchical disambiguation to compute rules from left to right, which merges all lists.
We can write a method to show this result:
def L(klass) : # klass Avoid the class keyword
return [k.__name__ for k in klass.__mro__]
L(MyClass)
====> ['MyClass'.'Base1'.'Base2'.'CommonBase'.'object']
# object All built-in ancestors in Python, so it comes at the end
Copy the code
The class’s __mro__ holds the result, and only then does the class finish loading. You can call myclass.mro () to get the result.
So mrO in Python is essentially the C3 method, and once you understand C3, you can use super() to know which ones will be executed first and which ones will be executed later