In Python sind Methoden nur Schlüssel-Wert-Paare im Wörterbuch, das an die Klasse angehängt ist. Wenn Sie eine Klasse von einer Basisklasse ableiten, sagen Sie im Wesentlichen, dass der Methodenname im ersten abgeleiteten Klassenwörterbuch und dann im Basisklassenwörterbuch angezeigt wird. Um eine Methode zu "überschreiben", deklarieren Sie die Methode einfach erneut in der abgeleiteten Klasse.
Was ist, wenn Sie die Signatur der überschriebenen Methode in der abgeleiteten Klasse ändern? Alles funktioniert ordnungsgemäß, wenn sich der Aufruf auf der abgeleiteten Instanz befindet. Wenn Sie den Aufruf jedoch auf der Basisinstanz ausführen, wird eine Fehlermeldung angezeigt, da die Basisklasse für denselben Methodennamen eine andere Signatur verwendet.
Es gibt jedoch häufige Szenarien, in denen die abgeleitete Klassenmethode zusätzliche Parameter haben soll und der Methodenaufruf auch ohne Fehler auf der Basis funktionieren soll. Dies wird als "Liskov-Substitutionsprinzip" (oder LSP ) bezeichnet, das garantiert, dass Personen, die von der Basisinstanz zur abgeleiteten Instanz oder umgekehrt wechseln, ihren Code nicht überarbeiten müssen. Um dies in Python zu tun, müssen Sie Ihre Basisklasse mit der folgenden Technik entwerfen:
class Base:
def hello(self, name, *args, **kwargs):
print("Hello", name)
class Derived(Base):
def hello(self, name, age=None, *args, **kwargs):
super(Derived, self).hello(name, age, *args, **kwargs)
print('Your age is ', age)
b = Base()
d = Derived()
b.hello('Alice')
b.hello('Bob', age=24)
d.hello('Rick')
d.hello('John', age=30)
Oben wird gedruckt:
Hallo Alice
Hallo Bob
Hallo Rick
Dein Alter ist Keine
Hallo John
Ihr Alter ist 30
.
Spielen Sie mit diesem Code
*args
? Wenn nicht,d.hello("John", "blue", age=30)
funktioniert Code wie nicht. Ich meine, im Allgemeinen sollten Positionsargumente immer vor kwargs definiert werdenage
hier) auch nach Position oder nur als kwarg festgelegt werden. Beachten Sie, dass Ihr Vorschlag nur in Python 3 funktioniert, wo Sie nur Argumente für Schlüsselwörter angeben können*
. Siehe zB das .Python lässt dies zu, aber wenn
method1()
es aus externem Code ausgeführt werden soll, sollten Sie dies möglicherweise noch einmal überdenken, da es gegen LSP verstößt und daher nicht immer ordnungsgemäß funktioniert.quelle
Super.method1(param1=None, param2=None, param3=None)
sie immer noch gegen LSP verstößt, wenn sie in Unterklassen alsSub.method1(param1, param2, param3)
richtig definiert ist ? Da Attribute in einem Fall obligatorisch sind, im anderen nicht. Nach meinem Verständnis wäre die einzige Möglichkeit, LSP nicht zu verletzen, ohne die Unterklassenschnittstelle zu ändern, die Parameter ohne Standardwerte auf dem übergeordneten Element zu haben. Bin ich richtig oder überinterpretiere ich den LSP?method1
ist__init__
, wo LSP nicht giltIn Python sind alle Klassenmethoden "virtuell" (in Bezug auf C ++). Wenn Sie also im Fall Ihres Codes eine Superklasse aufrufen
method1()
möchten, muss dies sein:class Super(): def method1(self): pass class Sub(Super): def method1(self, param1, param2, param3): super(Sub, self).method1() # a proxy object, see http://docs.python.org/library/functions.html#super pass
Und die Methodensignatur spielt eine Rolle. Sie können eine Methode wie diese nicht aufrufen:
quelle
Sie könnten so etwas tun, wenn es in Ordnung ist, Standardargumente zu verwenden:
>>> class Super(): ... def method1(self): ... print("Super") ... >>> class Sub(Super): ... def method1(self, param1="X"): ... super(Sub, self).method1() ... print("Sub" + param1) ... >>> sup = Super() >>> sub = Sub() >>> sup.method1() Super >>> sub.method1() Super SubX
quelle
Es wird klappen:
>>> class Foo(object): ... def Bar(self): ... print 'Foo' ... def Baz(self): ... self.Bar() ... >>> class Foo2(Foo): ... def Bar(self): ... print 'Foo2' ... >>> foo = Foo() >>> foo.Baz() Foo >>> >>> foo2 = Foo2() >>> foo2.Baz() Foo2
Dies wird jedoch im Allgemeinen nicht empfohlen. Schauen Sie sich die Antwort von S.Lott an : Methoden mit demselben Namen und unterschiedlichen Argumenten riechen nach Code .
quelle
Ja. Aufrufe von "method1" gehen immer in die Unterklasse. Die Methodensignatur in Python besteht nur aus dem Namen und nicht aus der Argumentliste.
quelle