Multiple inheritance: overridden methods containing super()-calls

2024/9/19 9:07:32

With the file super5.py:

class A:def m(self):print("m of A called")class B(A):def m(self):print("m of B called")super().m()class C(A):def m(self):print("m of C called")super().m()class D(B,C):def m(self):print("m of D called")super().m()

we can do the following:

>>> from super5 import D
>>> x = D()
>>> x.m()
m of D called
m of B called
m of C called
m of A called

To me, this doesn't make sense, because when I execute x.m(), I expect the following to happen:

  1. The first line of m of D is executed and thus "m of D called" is output.
  2. The second line, super().m() is executed, which first takes us to m of B.
  3. In m of B, "m of B called" is first output, and then, m of A is executed due to the super.m() call in m of B, and "m of A called" is output.
  4. m of C is executed in a fashion analogous to 3.

As you can see, what I expect to see is:

m of D called
m of B called
m of A called
m of C called
m of A called

Why am I wrong? Is python somehow keeping track of the number of super() calls to a particular superclass and limiting the execution to 1?

Answer

No, Python keep a track of all super classes in a special __mro__ attribute (Method Resolution Order in new-style classes):

print(D.__mro__)

You get:

(<class 'D'>, <class 'B'>, <class 'C'>, <class 'A'>, <class 'object'>)

So, when you call super, it follow this list in order.

See this question: What does mro() do?.

Everything is explained in the official document in the chapter "Multiple Inheritance".

For most purposes, in the simplest cases, you can think of the search for attributes inherited from a parent class as depth-first, left-to-right, not searching twice in the same class where there is an overlap in the hierarchy. Thus, if an attribute is not found in DerivedClassName, it is searched for in Base1, then (recursively) in the base classes of Base1, and if it was not found there, it was searched for in Base2, and so on.

In fact, it is slightly more complex than that; the method resolution order changes dynamically to support cooperative calls to super(). This approach is known in some other multiple-inheritance languages as call-next-method and is more powerful than the super call found in single-inheritance languages.

Dynamic ordering is necessary because all cases of multiple inheritance exhibit one or more diamond relationships (where at least one of the parent classes can be accessed through multiple paths from the bottommost class). For example, all classes inherit from object, so any case of multiple inheritance provides more than one path to reach object. To keep the base classes from being accessed more than once, the dynamic algorithm linearizes the search order in a way that preserves the left-to-right ordering specified in each class, that calls each parent only once, and that is monotonic (meaning that a class can be subclassed without affecting the precedence order of its parents). Taken together, these properties make it possible to design reliable and extensible classes with multiple inheritance.

https://en.xdnf.cn/q/72229.html

Related Q&A

Specifying the output file name in Apache Spark

I have a MapReduce job that Im trying to migrate to PySpark. Is there any way of defining the name of the output file, rather than getting part-xxxxx?In MR, I was using the org.apache.hadoop.mapred.li…

How to plot two DataFrame on same graph for comparison

I have two DataFrames (trail1 and trail2) with the following columns: Genre, City, and Number Sold. Now I want to create a bar graph of both data sets for a side by side comparison of Genre vs. total N…

Babel doesnt recognize jinja2 extraction method for language support

Im adding language translation support to my project. The code is on Python and has jinja2 in the html files, and Javascript.Im trying to use Babel to do the translation, but it doesnt recognize the ex…

Automatically simplifying/refactoring Python code (e.g. for loops - list comprehension)? [closed]

Closed. This question is seeking recommendations for books, tools, software libraries, and more. It does not meet Stack Overflow guidelines. It is not currently accepting answers.We don’t allow questi…

Knowing the number of iterations needed for convergence in SVR scikit-learn

I am trying to optimize an SVR model and facing a problem because of overfitting, to overcome this I have tried to decrease the number of iterations instead of leaving it until convergence.To compare …

Why is `NaN` considered smaller than `-np.inf` in numpy?

What is the reason that NaNs are considered less than -np.inf in any comparisons involving np.min or np.argmin?import numpy as np In [73]: m = np.array([np.nan, 1., 0., -np.inf]) In [74]: n = np.array…

recursion within a class

I am trying to place a recursive formula inside a class statementclass SomeNode:def __init__(self, a):leng = len(a)half= leng/2self.firstnode=a[0][0]self.child1=SomeNode([a[i]for k in range(leng)])self…

There is an example of Spyne client?

Im trying to use spyne (http://spyne.io) in my server with ZeroMQ and MsgPack. Ive followed the examples to program the server side, but i cant find any example that helps me to know how to program the…

Safely bind method from one class to another class in Python [duplicate]

This question already has answers here:What is the difference between a function, an unbound method and a bound method?(6 answers)Closed 5 years ago.I know I can attach a function to a class and make …

Basic Python OpenCV cropping and resizing

can someone help me with a little cropping algorithm? its openCV.. im trying to figure this out. I know the method is crop = image[y:y1, x:x1]. If I have an image with new_dimensionXxnew_dimensionY pi…