Reputation: 46
I have two classes (Table and Button) inherited from the same class Widget. Both subclasses have their own keyEvent() methods and both call Widget.keyEvent() when necessary. I want to modify the keyEvent() behaviour for both classes in the same way (for example make A
and D
keys to trigger LEFT
and RIGHT
keys).
This code works exactly as I want
class KeyModifier:
def keyEvent():
# some lines of code
super().keyEvent()
class MyTable(KeyModifier,Table):
pass
class MyButton(KeyModifier,Button):
pass
But Pylance is angry because KeyModifier.super() doesn't have any keyEvent() method (which is true).
Is there a way to do it better? Also, I would like Pylance to warn me when using the KeyModifier with something not inherited from Widget.
This example comes from a PyQT app, but the question is more general.
Edit: Making KeyModifier a subclasss of Widget makes KeyModifier.super().keyEvent() call Widget.keyEvent() and I want to call the child class method (Table.keyEvent() or Button.keyEvent())
Upvotes: 0
Views: 80
Reputation: 46
I've found a workaround as I don't really have to manage any class methods but the event that is being handled.
def KeyModifier(event: Event) -> Event:
# some lines of code and edit 'event' if necessary
return event
class MyButton(Button):
def keyEvent(self, event: Event):
super().keyEvent(KeyModifier(event))
I think this is the simplest way to write it. Thank you all for your suggestions :)
Upvotes: 0
Reputation: 8076
If you make KeyModifier
inherit from Widget
, the warning will be gone because keyEvent
will actually be defined for the object. If you also add super().keyEvent()
calls to your modified classes, all the proper events will fire thanks to something called MRO - Method Resolution Order.
class Base:
def event(self):
print("Base")
class A(Base):
def event(self):
print("A")
class B(Base):
def event(self):
print("B")
class Modifier(Base):
def event(self):
print("Modified")
super().event()
class ModifiedA(Modifier, A):
def event(self):
print("ModifiedA")
super().event()
class ModifiedB(Modifier, B):
def event(self):
print("ModifiedB")
super().event()
ModifiedA().event()
Output:
ModifiedA
Modified
A
It is important to note that if A
and B
do not call a super on their own (I'm fairly certain that PyQt widgets DO call their parent though), Modifier
has to be the first class inherited, as it will cause it to be first in MRO and have a chance to call the other class method in turn.
Upvotes: 0
Reputation: 11
Does it help?
from abc import abstractmethod
class Table:
pass
class Button:
pass
class KeyModifier:
@abstractmethod
def custom_operation(self):
pass
def key_event(self, condition):
if condition:
self.custom_operation()
class MyTable(KeyModifier, Table):
def __init__(self):
super(MyTable, self).__init__()
def custom_operation(self):
pass
class MyButton(KeyModifier, Button):
def custom_operation(self):
pass
Upvotes: 1