Method Resolution Order–python class methods parsing order

Source: Internet
Author: User

In a programming language that supports multiple inheritance, the search order of the base class when the lookup method is specific from that class is often referred to as the method Resolution order, or MRO. (Finding other properties in Python also follows the same rule.) MRO is simple for languages that support only single-inheritance, but the choice of MRO algorithms is subtle when considering multiple inheritance scenarios. Python has three different types of MRO: Classic, Python2.2, and Python2.3 (also known as C3). Only the last one, the C3 algorithm, is reserved in Python 3.

The classic class employs a simple MRO mechanism: when searching for a method, the search base class has simple depth precedence from left to right. The first matching object in the search process is returned as a result. For example, consider the following class:

class A:     def Pass class Pass class C:     def Pass class Pass

For instance X of Class D, its classic MRO result is the class d,b,a,c order. So the lookup method X.save () will get A.save () (instead of C.save ()). This mechanism works well for simple situations, but for more complex multiple inheritance relationships, the exposed problems are more obvious. One of the problems is the method lookup order when it comes to "diamond inheritance." For example:

class A:     def Pass class Pass class C (A):     def Pass class Pass

Class D here inherits from Class B and Class C, and Class B and Class C Inherit from Class A. With traditional MRO, the search order in a class when finding a method is D, B, A, C, a. Therefore, the statement x.save () will call A.save () as before. However, this may not be what you need! Since both B and C inherit from a, others can argue that the redefined method C.save () can be seen as "more specific" than the method in Class A (in fact, it is possible that c.save () will call A.save ()), so C.save () is what you should call. If the Save method is used to persist the state of the object, not calling C.save () causes the state of C to be discarded, and the program is faulted.

Although there are few such multiple inheritance codes in Python code at the time, the advent of the "new Class" (New-style Class) makes it a common phenomenon. This is because all new classes inherit from the base class of object. Therefore, multiple inheritance involving the new class always produces the diamond relationship described earlier. For example:

class Pass class C (object):     def __setattr__ Pass class Pass

Also, object defines methods (such as __setattr__ ()) that can be extended by subclasses, and the parsing order is more critical. In the example above the code, the method c.__setattr__ should be applied to the instance of Class D.

In order to solve the problem of the method parsing order of the new class introduced in Python2.2, I took the option of calculating its MRO when the class was defined and storing it as a property of the class object. The MRO in the official documentation is calculated as depth first, traversing the base class from left to right, which is consistent with the classic MRO, but if any class is duplicated in the search, only the last occurrence is retained and the remainder is removed from the MRO list. So in our previous example, the search order would be D, B, C, a (classic class with classic MRO, then D, B, A, C, a).

In fact, MRO calculations are more complex than the documentation says. I have found that in some cases the new MRO algorithm results are not ideal. There is also a special case for handling two base classes in a different order in two different derived classes, and those two derived classes are inherited by another class. As shown in the following code:

class Pass class Pass class Pass class Pass class Pass

Using the new MRO algorithm described in the documentation, the MRO for these classes is Z, X, Y, B, A, object. (The object here is a generic base class.) )。 However, I do not want the result to appear before a B. So the actual MRO will exchange its order, producing Z, X, Y, A, B, object. Intuitively, the algorithm tries to keep the order in which the base class first appears during the search. For example, for Class Z, their base class x should be searched first, because the sort in the inherited list is the most forward. Since X inherits from a and the B,MRO algorithm tries to keep its order. This is an algorithm that I actually implemented in Python2.2, but the document mentions only the previous algorithms that do not include exception handling (I naively think that this small difference does not have to be explicit.) )。

However, shortly after the introduction of the new class in Python 2.2, Samuele Pedroni discovered that the MRO algorithm in the document was inconsistent with the results observed in the actual code. Moreover, inconsistencies may occur outside of the above-mentioned exceptions. The results discussed in detail suggest that the MRO used by Python2.2 is bad, and Python should use the C3 linearization algorithm, which is detailed in the paper "A monotonic superclass linearization for Dylan" (K. Barrett, et AL, presented at OOPSLA ' 96).

Essentially, the main problem with Python 2.2 MRO is the inability to maintain monotonicity (monotonicity). In a complex multi-level inheritance scenario, each inheritance relationship determines a direct lookup order, and if Class A inherits Class B, the MRO should obviously look for a after a and b. Similarly, if Class B inherits Class C and Class D multiple, then Class B should precede Class C in the search order, and Class C should precede Class D.

In complex multi-level inheritance situations, it is always possible to satisfy this rule as to maintain monotonicity. That is, when you decide that class A will be found before class B, you should never encounter a situation where Class B needs to be looked up before class A (otherwise, the result is undefined and you should reject the multi-level inheritance in this case). The previous MRO algorithm failed to do this, and the new C3 algorithm was effective in ensuring monotonicity. Basically, the purpose of C3 is to allow you to sort through all the inheritance relationships in a complex hierarchical inheritance, and if all the order relationships are satisfied, the order results will satisfy the monotonicity. Otherwise, unable to get a definite order, the algorithm will error, refused to run.

So, in Python 2.3, I abandoned the 2.2 MRO algorithm in my manual workshop, and replaced it with an C3 algorithm that was tested by the academic audit. One of the results is that Python rejects this kind of inheritance when there is a base class order inconsistency in a multi-level inheritance. Or in the previous example, there is a sequential inconsistency for Class X and Class Y, and for class X, the rule decision Class A should be checked before class B. For class Y, however, the rule thinks that Class B should be checked before class A. This inconsistency is acceptable in individual cases, but if x and Y are common as the base class for another class (the class Z defined in the example), the C3 algorithm rejects the inheritance. This is also the "errors should never pass silently" rule that corresponds to Zen of Python.

English original link: http://python-history.blogspot.com/2010/06/method-resolution-order.html
Original Author: Guido van Rossum

Translator: Jabari-bi

Method Resolution Order–python class methods parsing order

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.