Multiple Inheritance Ambiguity in Python - python-3.x

Diamond Problem
class A():
def method(self):
print ("I am from class A")
class B(A):
def method(self):
print("I am from B")
super().method()
class C(A):
def method(self):
print ("I am from class C")
class D(B,C):
def method(self):
print ("I am from class D")
super().method()
d = D()
d.method()
I want to get the output as :
I am from class D
I am from B
I am from class A
However, i get the output as:
I am from class D
I am from B
I am from class C
How do i call method the method of A class using instance of D class? Is MRO a possible solution to this?

In Python 3 children always come in MRO before parents, this is needed to allow overrides work sensibly:
>>> D.__mro__
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
In multiple inheritance, super() does not simply refer to the parent, it is used to get the next class in MRO. If you know what method of what class you want to call, do it directly:
class D(B,C):
def method(self):
print("I am from class D")
A.method(self)

class A():
def method(self):
print ("I am from class A")
class B(A):
def method(self):
print("I am from B")
A.method(self)
class C(A):
def method(self):
print ("I am from class C")
class D(B,C):
def method(self):
print ("I am from class D")
super().method()
d = D()
d.method()

Related

Why can't call all __init__ when super() with Multiple Inheritance?

Show the code:
class state():
def __init__(self):
print('in the state class')
self.state = "main state"
class event():
def __init__(self):
print("in the event class")
self.event = "main event"
class happystate(state,event):
def __init__(self):
print('in the happy state class')
super(state,self).__init__()
super(event,self).__init__()
happystate has two base class--state and event,initialize the happystate.
a = happystate()
in the happy state class
in the event class
Why can't call state class?
If you don't use super().__init__() in other classes, and you have multiple inheritance, python stops running other __init__ methods.
class state():
def __init__(self):
super().__init__()
print('in the state class')
self.state = "main state"
class event():
def __init__(self):
super().__init__()
print("in the event class")
self.event = "main event"
class happystate(state,event):
def __init__(self):
print('in the happy state class')
super().__init__()
I am adding some references:
From Raymond Hettinger
StackOverflow
As MisterMiyagi say that super(state,self).init does not mean "init on the super class which is state", it means "init on the super class which is in self's mro after state".
We can remove all the super().__init__() in class state and event with such other way as below:
class state():
def __init__(self):
print('in the state class')
self.state = "main state"
class event():
def __init__(self):
print("in the event class")
self.event = "main event"
class happystate(state,event):
def __init__(self):
print('in the happy state class')
super(happystate,self).__init__()
super(state,self).__init__()
Initialize the class happystate:
>>> x = happystate()
in the happy state class
in the state class
in the event class
>>> x.state
'main state'
>>> x.event
'main event'

How to Access Outer class variables in Inner Class (Python)?

How to access the variables of the outer class in the Inner Class?
class Student:
def __init__(self,Name,rollNumber):
self.Name=Name
self.rollNumber=rollNumber
self.lap=self.Laptop()
def Show(self):
print(self.Name)
print(self.lap.show())
class Laptop:
def __init__(self):
self.brand = "Mac"
self.cpu = "i9"
self.ram = 16
def show(self):
return self.brand
#staticmethod
def Show():
return s1.Name
s1=Student("Teja",2)
print(s1.Name,s1.rollNumber)
s1.Show()
print(s1.lap.brand)
system=s1.lap
print(system.brand)
print(system.cpu)
print(system.show())
print(system.Show())

Python3: Do subclasses of an abstract class inherit its magic methods?

Here's the tea: I'm writing a small Monopoly game using python. I've made this little class family to represent the bills. There's a base abstract class called Bill which inherits from the abc.ABC class.
Code:
from abc import ABC, abstractmethod
import colorama
colorama.init(autoreset=True, strip=True)
class Bill(ABC):
#Abstract Properties (must be overriden in subclasses)
#property
#abstractmethod
def count(self):
return 0
#property
#abstractmethod
def color(self): # colorama background color
return 0
#property
#abstractmethod
def worth(self): # integer representing the bill's worth
return 0
# Dunder methods (The same across class family)
def __add__(self, other):
return self.worth + other.worth
def __str__(self):
return f" {self.color} {self.worth}"
class One(Bill):
def __init__(self):
self.__count = 0
self.__color = "\033[0m"
self.__worth = 0
#super().init() ??
# Override Abstract Methods
#property
def count(self):
return self.__count
#count.setter
def count(self, amount):
self.__count += 1
#property
def worth(self):
return 1
#property
def color(self):
return colorama.Back.WHITE
My question is whether my subclasses will inherit the Bill class's dunder methods.
And if not, do I need to include super().__init__() in the One class's __init__ method?

Python Class Multiple Inheritance Only Inherit Variables From One Parent?

I'm confused about the way Python class inherit from multiple parent classes.
If the parent classes all inherit from the same grand-parent class, everything is wonderful.
# grand-parent class
class Z():
def __init__(self):
pass
# parent class A
class A(Z):
def __init__(self):
super().__init__()
self.x = 1
# parent class B
class B(Z):
def __init__(self):
super().__init__()
self.y = 2
# parent class C
class C(Z):
def __init__(self):
super().__init__()
self.z = 3
# target class D
class D(A, B, C):
def __init__(self):
super().__init__()
d = D()
print(vars(d))
#{'x': 1, 'y': 2, 'z': 3}
Without the same grand-parent class, only variables from the first parent class is inherited.
# parent class A
class A():
def __init__(self):
self.x = 1
# parent class B
class B():
def __init__(self):
self.y = 2
# parent class C
class C():
def __init__(self):
self.z = 3
# target class D
class D(A, B, C):
def __init__(self):
super().__init__()
d = D()
print(vars(d))
#{'x': 1}
Python's method resolution order works from Left to Right. It will only call the init method of the first class(A in your case).
This will give you the desired result-
class A():
def __init__(self):
super().__init__()
self.x = 1
# parent class B
class B():
def __init__(self):
super().__init__()
self.y = 2
# parent class C
class C():
def __init__(self):
self.z = 3
# target class D
class D(A, B, C):
def __init__(self):
super().__init__()
d = D()
print(vars(d))

change method resolution order

is it possible to change the method resolution order?
class A(object):
def __init__(self, a):
self.a=a
def method(self):
print('A method')
class B(object):
def __init__(self, b1, b2):
self.b1=b1
self.b2=b2
def method(self):
print('B method')
class C(A, B):
def __init__(self, name, **kwargs):
if name=='A':
A.__init__(self, a=kwargs['a'])
elif name=='B':
B.__init__(self, b1=kwargs['b1'], b2=kwargs['b2'])
I want change the MRO if the input name is 'B', so that when i call:
>>>c=C(name='B', b1=2, b2=3)
>>>c.method()
it returns 'B method'.
Thanks
Just change the definition of the C class to :
class C(B, A):
...
ie : change the order of the inherited classes.

Resources