このプロパティが派生クラスで上書きされている場合、基本クラスのプロパティを呼び出す方法は?
-
06-07-2019 - |
質問
私は、いくつかのクラスをゲッターとセッターの広範囲な使用から、より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()
(それはあなたの説明から何かを見逃していない限り)