私は、いくつかのクラスをゲッターとセッターの広範囲な使用から、より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
を使用する代替方法があります。
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
他の人がすでに答えているように、それは次のとおりです。
super(B, self).prop
またはPython 3:
super().prop
これは、ゲッター自体ではなく、プロパティのゲッターによって返される値を返しますが、ゲッターを拡張するには十分です。
私がこれまでに見た中で最高の推奨事項は次のとおりです。
A.prop.fset(self, value)
私はこれが優れていると信じています:
super(B, self.__class__).prop.fset(self, value)
この例では、両方のオプションは同等ですが、superを使用すると、B
の基本クラスから独立しているという利点があります。 B
がプロパティを拡張するC
クラスから継承する場合、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)
プロパティにセッターがない場合は、セッターとゲッターの両方の動作を変更する場合でも、それらの両方を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