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.
Related
I was trying to understand this example working.
class P:
def __init__(self):
self.__x=100
self.y=200
def print(self):
print(self.__x, self.y)
class C(P):
def __init__(self):
super().__init__() <-------------------
self.__x=300
self.y=400
d = C()
d.print()
output: 100 400
class P:
def __init__(self):
self.__x=100
self.y=200
def print(self):
print(self.__x, self.y)
class C(P):
def __init__(self):
self.__x=300
self.y=400
super().__init__() <--------------------
d = C()
d.print()
output: 100 200
Can someone explain the execution flow of the above codes leading to separate outputs?
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())
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))
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()
I'd like to create a new class that inherits two subclasses of QWidget. I know multi-inheritance isn't possible in pyqt, but how could I manage to have the properties of both parent classes in one subclass?
What I wish I could do is as follows:
class A(QWidget):
def __init__(self, widget, parent=None):
widget.destroyed.connect(self.destroy_handler)
#pyqtSlot()
def destroy_handler(self):
pass
class B (A, QStatusBar):
def __init__(self, widget, parent=None):
A.__init__(self, widget)
QStatusBar.__init__(self, parent)
#pyqtSlot()
def destroyed_handler(self):
print("Destroyed")
I finally found how to do it: first of all, the problems came from A and QStatusBar inheriting QWidget. We can't change QStatusBar, so we must changer A.
A shouldn't inherit QWidget: so let's create another class, AInterface, like that:
class AInterface(QObject):
def __init__(self, a, parent=None)
super().__init__(parent=parent)
self.a = a
self.connect_signal()
def connect_signal(self, widget):
widget.destroyed.connect(self.handler)
#pyqtSlot()
def handler(self):
self.a.handler()
A has now the following implementation:
class A:
def __init__(self, widget):
a.widget = widget
a.interface = AInterface(self)
def handler(self):
pass
Thus, now we can create subclasses inheriting not only A but also any QObject, like this:
class B(QStatusBar, A):
def __init__(self, widget, parent=None):
QStatusBar.__init__(self, parent=parent, wiget=widget)
A.__init__(self, widget)
def handler(self):
self.show('Destroyed', 3000)
Notice the widget=widget in the constructor of QStatusBar: if we don't specify it, a TypeError is thrown...