web-dev-qa-db-ja.com

Pythonメソッドのオーバーライド、署名は重要ですか?

私が持っているとしましょう

class Super():
  def method1():
    pass

class Sub(Super):
  def method1(param1, param2, param3):
      stuff

これは正しいです? method1の呼び出しは常にサブクラスになりますか?私の計画は、それぞれが異なるパラメータでmethod1をオーバーライドする2つのサブクラスを持つことです

44
asdasasdsa

Pythonはこれを許可しますが、method1()が外部コードから実行されることを意図している場合、 [〜#〜] lsp [〜#〜] に違反するため、これを再検討することができます。 =したがって、常に適切に動作するとは限りません。

Pythonでは、異なるシグネチャを持つメソッドを「オーバーライド」することができますが、シグネチャが異なる場合でも同じクラスに同じ名前の2つのメソッドを持つことはできません(つまり、メソッドのオーバーロードはありません)。メソッドをオーバーライドする場合、オブジェクトに対して定義されているパラメーターの数が間違っているメソッドを呼び出すと、エラーが発生します。 Pythonのメソッドは、オブジェクトにアタッチされたディクショナリのキーと値のペアにすぎず、同じキーのベースクラスディクショナリから最初にコピーされたディクショナリの値を単に「オーバーライド」することに注意してください。

派生クラスメソッドに基本クラスよりもadditionalパラメーターが必要なシナリオが頻繁にあります。これをPythonで保存しながら [〜#〜] lsp [〜#〜] で行うには、次の手法を使用できます。

class Base:
    def hello(self, name, *kargs, **kwargs):
        print("Hello", name)

class Derived(Base):
      def hello(self, name, age=None, *kargs, **kwargs):
          super(Derived, self).hello(name, age, *kargs, **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)

上記が印刷されます:

Hello Alice
Hello Bob
Hello Rick
Your age is  None
Hello John
Your age is  30

このコードで遊ぶ

12
Shital Shah

Pythonでは、すべてのクラスメソッドは「仮想」です(C++の観点から)。したがって、コードの場合、スーパークラスでmethod1()を呼び出すには、次のようにする必要があります。

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

そして、メソッドのシグネチャは重要です。次のようなメソッドを呼び出すことはできません。

sub = Sub()
sub.method1() 
1
Zaur Nasibov

それが動作します:

>>> 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

ただし、これは一般的に推奨されません。 S.Lott の答えを見てください: 同じ名前で異なる引数を持つメソッドはコードの匂いです

1
quasistoic

デフォルトの引数を使用しても問題ない場合は、次のようにすることができます。

>>> 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
1
Zitrax