web-dev-qa-db-ja.com

pythonで静的メソッドをオーバーライドする

ここで 最初の回答 を参照して、ここでpythonのバインドされたメソッドとバインドされていないメソッドについて、質問があります。

_class Test:
    def method_one(self):
        print "Called method_one"
    @staticmethod
    def method_two():
        print "Called method_two"
    @staticmethod
    def method_three():
        Test.method_two()
class T2(Test):
    @staticmethod
    def method_two():
        print "T2"
a_test = Test()
a_test.method_one()
a_test.method_two()
a_test.method_three()
b_test = T2()
b_test.method_three()
_

出力を生成します:

_Called method_one
Called method_two
Called method_two
Called method_two
_

Pythonで静的メソッドをオーバーライドする方法はありますか?

私はb_test.method_three()が "T2"を出力することを期待していましたが、そうではありません(代わりに "Called method_two"を出力します)。

45
Emma

そこで使用しているフォームでは、呼び出すクラスの静的method_twoを明示的に指定しています。 method_threeがクラスメソッドであり、cls.method_twoを呼び出した場合、必要な結果が得られます。

class Test:
    def method_one(self):
        print "Called method_one"
    @staticmethod
    def method_two():
        print "Called method_two"
    @classmethod
    def method_three(cls):
        cls.method_two()

class T2(Test):
    @staticmethod
    def method_two():
        print "T2"

a_test = Test()
a_test.method_one()  # -> Called method_one
a_test.method_two()  # -> Called method_two
a_test.method_three()  # -> Called method_two

b_test = T2()
b_test.method_three()  # -> T2
Test.method_two()  # -> Called method_two
T2.method_three()  # -> T2
63
lostlogic

表示される動作は、予想される動作です。静的メソッドは...静的です。 Testで定義されているmethod_three()を呼び出すと、Testで定義されているmethod_two()が確実に呼び出されます。

この適切な動作を「回避する」方法については...

最善の方法は、仮想動作が必要なときにメソッドを仮想化することです。静的メソッドを使用するライブラリコードで仮想にしたい場合は、さらに深く調べて、理由があるのか​​、それとも単なる見落としなのかを確認します。

それ以外の場合は、method_three()を呼び出す新しいT2.method_two()を_T2_で定義できます。

3
dwc

さらに、インスタンスなしで「仮想静的」関数を呼び出したい場合は、次のように進めることができます。

  1. 基本クラスの関数を次のように非静的に宣言します。

    class Base:
        def my_fun(self):
            print('my_fun base')
    
    class Derived(Base):
        def my_fun(self):
            print('my_fun derived')
    
  2. 次のように、インスタンスではないクラスタイプを渡すことで呼び出します。

    Derived.my_fun(Derived)
    

これは、実行時にのみ認識される変数「class_type」がある場合に便利です。

0
Ytsen de Boer