だから、私はPythonでプロパティの特定の関数(たとえば、ゲッター、セッターなど)をオーバーライドできるようにするための最良の(最小限のコードで最もエレガントな)方法を見つけようとしています。私は、すべてのメソッドが同じインデントされたコードのブロックにカプセル化されているという事実のために、次のプロパティの実行方法が好きです(1つのプロパティを処理する関数が停止し、次に開始):
_@apply
def foo():
"""A foobar"""
def fget(self):
return self._foo
def fset(self, val):
self._foo = val
return property(**locals())
_
ただし、この方法でプロパティを定義するクラスから継承し、たとえばfoo
setter関数をオーバーライドする場合、注意が必要です。私はいくつかの検索を行いましたが、見つかった答えのほとんどは、基本クラスで個別の関数を定義することでした(たとえば、getFoo
とsetFoo
)、それらから明示的にプロパティ定義を作成します(例:foo = property(lambda x: x.getFoo(), lambda x, y: x.setFoo(y), lambda x: x.delFoo())
)、必要に応じてgetFoo
、setFoo
、およびdelFoo
をオーバーライドします。
このソリューションが嫌いなのは、プロパティごとにlambasを定義してから、各関数呼び出しを書き出す必要があるからです(property(**locals())
を実行する直前の場合)。また、元々持っていたカプセル化も得られません。
理想的には、私ができることは次のようなものです。
_class A(object):
def __init__(self):
self.foo = 8
@apply
def foo():
"""A foobar"""
def fget(self):
return self._foo
def fset(self, val):
self._foo = val
return property(**locals())
class ATimesTwo(A):
@some_decorator
def foo():
def fset(self, val):
self._foo = val * 2
return something
_
そして、出力は次のようになります。
_>>> a = A()
>>> a.foo
8
>>> b = ATimesTwo()
>>> b.foo
16
_
基本的に、ATimesTwo
はA
からgetter関数を継承しますが、setter関数をオーバーライドします。誰かがこれを行う方法を知っていますか(上記の例に似た方法で)? _some_decorator
_はどの関数になり、foo
関数は何を返す必要がありますか?
これは聞いたことがあると思いますが、apply
は8年の間廃止されました。Python 2.3。 locals()
の使用は、Python-明示的は暗黙的よりも優れています。インデントの増加が本当に好きなら、スローアウェイオブジェクトを作成する必要はありません
_if True:
@property
def foo(self):
return self._foo
@foo.setter
def foo(self, val):
self._foo = val
_
locals
を乱用しない、apply
を使用する、余分なオブジェクトを作成する必要がある、またはfoo = foo()
で後から行を必要とせず、ブロックの終わりを見にくくする。 property
を使用する従来の方法でも同様に機能します。通常どおりfoo = property(fget, fset)
を実行します。
任意のサブクラスのプロパティをオーバーライドする場合は、 このようなレシピ を使用できます。
サブクラスがプロパティが定義された場所を知っている場合、次のようにします。
_class ATimesTwo(A):
@A.foo.setter
def foo(self, val):
self._foo = val * 2
_
property
デコレータのPython docs は、次のイディオムを示唆しています。
class C(object):
def __init__(self):
self._x = None
@property
def x(self):
return self._x
@x.setter
def x(self, value):
self._x = value
@x.deleter
def x(self):
del self._x
そして、サブクラスは次のように単一のセッター/ゲッターをオーバーライドできます。
class C2(C):
@C.x.getter
def x(self):
return self._x * -1
複数のメソッドをオーバーライドするには、次のようなことを行う必要があるため、これは少し厄介です。
class C3(C):
@C.x.getter
def x(self):
return self._x * -1
# C3 now has an x property with a modified getter
# so modify its setter rather than C.x's setter.
@x.setter
def x(self, value):
self._x = value * 2
もちろん、getter、setter、deleterをオーバーライドする時点で、おそらくC3のプロパティを再定義できます。