このプロパティが派生クラスで上書きされている場合、基本クラスのプロパティを呼び出す方法は?

StackOverflow https://stackoverflow.com/questions/1021464

質問

私は、いくつかのクラスをゲッターとセッターの広範囲な使用から、よりPython的なプロパティの使用に変更しています。

しかし、以前のgetterまたはsetterのいくつかが基本クラスの対応するメソッドを呼び出してから、他の何かを実行するため、スタックしています。しかし、プロパティでこれをどのように達成できますか?親クラスのプロパティゲッターまたはセッターを呼び出す方法

もちろん、属性自体を呼び出すだけで無限の再帰が得られます。

class Foo(object):

    @property
    def bar(self):
        return 5

    @bar.setter
    def bar(self, a):
        print a

class FooBar(Foo):

    @property
    def bar(self):
        # return the same value
        # as in the base class
        return self.bar # --> recursion!

    @bar.setter
    def bar(self, c):
        # perform the same action
        # as in the base class
        self.bar = c    # --> recursion!
        # then do something else
        print 'something else'

fb = FooBar()
fb.bar = 7
役に立ちましたか?

解決

プロパティによって呼び出される基本クラス関数を呼び出すことができると思うかもしれません:

class FooBar(Foo):

    @property
    def bar(self):
        # return the same value
        # as in the base class
        return Foo.bar(self)

これは試してみるのが最も明らかなことですが、バーは呼び出し可能なプロパティではなくプロパティなので、機能しません。

ただし、プロパティは単なるオブジェクトであり、対応する属性を見つけるゲッターメソッドがあります:

class FooBar(Foo):

    @property
    def bar(self):
        # return the same value
        # as in the base class
        return Foo.bar.fget(self)

他のヒント

スーパーがトリックを実行します。

return super().bar

Python 2.xでは、より詳細な構文を使用する必要があります:

return super(FooBar, self).bar

基本クラス名を明示的に参照する必要のない、 super を使用する代替手段があります。

ベースクラスA:

class A(object):
    def __init__(self):
        self._prop = None

    @property
    def prop(self):
        return self._prop

    @prop.setter
    def prop(self, value):
        self._prop = value

class B(A):
    # we want to extend prop here
    pass

Bで、親クラスAのプロパティゲッターにアクセスする:

他の人がすでに答えているように、それは:

super(B, self).prop

またはPython 3の場合:

super().prop

これは、ゲッター自体ではなく、プロパティのゲッターによって返された値を返しますが、ゲッターを拡張するには十分です。

Bで、親クラスAのプロパティセッターにアクセスします:

私がこれまでに見た中で最高の推奨事項は次のとおりです。

A.prop.fset(self, value)

この方が優れていると思います:

super(B, self.__class__).prop.fset(self, value)

この例では両方のオプションは同等ですが、superを使用すると B の基本クラスから独立しているという利点があります。 B がプロパティを拡張する C クラスから継承する場合、 B のコードを更新する必要はありません。

Aのプロパティを拡張するBの完全なコード:

class B(A):
    @property
    def prop(self):
        value = super(B, self).prop
        # do something with / modify value here
        return value

    @prop.setter
    def prop(self, value):
        # do something with / modify value here
        super(B, self.__class__).prop.fset(self, value)

1つの警告:

プロパティにセッターがない場合は、セッターとゲッターの両方の動作を変更する場合でも、それらの両方を B で定義する必要があります。

試用

@property
def bar:
    return super(FooBar, self).bar

Pythonが基本クラスプロパティの呼び出しをサポートしているかどうかはわかりませんが。プロパティは、実際には、指定された関数で設定され、クラス内のその名前を置き換える呼び出し可能なオブジェクトです。これは、使用可能なスーパー機能がないことを簡単に意味します。

常にproperty()関数を使用するように構文を切り替えることができます:

class Foo(object):

    def _getbar(self):
        return 5

    def _setbar(self, a):
        print a

    bar = property(_getbar, _setbar)

class FooBar(Foo):

    def _getbar(self):
        # return the same value
        # as in the base class
        return super(FooBar, self)._getbar()

    def bar(self, c):
        super(FooBar, self)._setbar(c)
        print "Something else"

    bar = property(_getbar, _setbar)

fb = FooBar()
fb.bar = 7
    class Base(object):
      def method(self):
        print "Base method was called"

    class Derived(Base):
      def method(self):
        super(Derived,self).method()
        print "Derived method was called"

    d = Derived()
    d.method()

(それはあなたの説明から何かを見逃していない限り)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top