サブクラスで上書きするプロパティ(getメソッド)を持つ基本クラスがあります。私の最初の考えは次のようなものでした:
class Foo(object):
def _get_age(self):
return 11
age = property(_get_age)
class Bar(Foo):
def _get_age(self):
return 44
これは機能しません(サブクラスbar.ageは11を返します)。動作するラムダ式を使用したソリューションを見つけました:
age = property(lambda self: self._get_age())
だから、これはプロパティを使用してサブクラスでそれらを上書きするための正しいソリューションですか、またはこれを行う他の好ましい方法はありますか?
property()
を繰り返すだけでなく、@classmethod
クラスメソッドをオーバーライドするときのデコレータ。
これは非常に冗長に見えますが、少なくともPython標準については、次のことに気付くでしょう:
1)読み取り専用プロパティの場合、property
をデコレーターとして使用できます。
class Foo(object):
@property
def age(self):
return 11
class Bar(Foo):
@property
def age(self):
return 44
2)Python 2.6、 プロパティはメソッドのペアを増やしましたsetter
およびdeleter
は一般プロパティに適用するために使用できます読み取り専用のショートカットは既に利用可能です:
class C(object):
@property
def x(self):
return self._x
@x.setter
def x(self, value):
self._x = value
選択した回答が、プロパティメソッドのオーバーライドを可能にする理想的な方法であることに同意しません。ゲッターとセッターがオーバーライドされることが予想される場合は、lambda self: self.<property func>
などのように、lambdaを使用してselfへのアクセスを提供できます。
これは(少なくとも)Pythonバージョン2.4から3.6で機能します。
直接property()呼び出しとしてではなく、デコレータとしてpropertyを使用してこれを行う方法を知っている人がいれば、それを聞きたいです!
例:
class Foo(object):
def _get_meow(self):
return self._meow + ' from a Foo'
def _set_meow(self, value):
self._meow = value
meow = property(fget=lambda self: self._get_meow(),
fset=lambda self, value: self._set_meow(value))
これにより、オーバーライドを簡単に実行できます。
class Bar(Foo):
def _get_meow(self):
return super(Bar, self)._get_meow() + ', altered by a Bar'
そのため:
>>> foo = Foo()
>>> bar = Bar()
>>> foo.meow, bar.meow = "meow", "meow"
>>> foo.meow
"meow from a Foo"
>>> bar.meow
"meow from a Foo, altered by a Bar"
これは geek at play で発見しました。
追加のクラスを作成せずに行う別の方法。 2つのうち1つだけをオーバーライドする場合に何をするかを示すために、setメソッドを追加しました。
class Foo(object):
def _get_age(self):
return 11
def _set_age(self, age):
self._age = age
age = property(_get_age, _set_age)
class Bar(Foo):
def _get_age(self):
return 44
age = property(_get_age, Foo._set_age)
これは非常に不自然な例ですが、アイデアを得る必要があります。
はい、これはそれを行う方法です。プロパティ宣言は、親クラスの定義が実行されるときに実行されます。つまり、親クラスに存在するメソッドのバージョンのみを「見る」ことができます。したがって、子クラスでこれらのメソッドの1つ以上を再定義する場合、子クラスのバージョンのメソッドを使用してプロパティを再宣言する必要があります。
私はあなたの解決策に同意します。これはオンザフライのテンプレート方法のようです。 この記事 あなたの問題に対処し、まさにあなたの解決策を提供します。
@ mr-b と同じですが、デコレータを使用します。
class Foo(object):
def _get_meow(self):
return self._meow + ' from a Foo'
def _set_meow(self, value):
self._meow = value
@property
def meow(self):
return self._get_meow()
@meow.setter
def meow(self, value):
self._set_meow(value)
これにより、オーバーライドを簡単に実行できます。
class Bar(Foo):
def _get_meow(self):
return super(Bar, self)._get_meow() + ', altered by a Bar'
このような何かが動作します
class HackedProperty(object):
def __init__(self, f):
self.f = f
def __get__(self, inst, owner):
return getattr(inst, self.f.__name__)()
class Foo(object):
def _get_age(self):
return 11
age = HackedProperty(_get_age)
class Bar(Foo):
def _get_age(self):
return 44
print Bar().age
print Foo().age
子クラスから親クラスにプロパティを設定する際に問題が発生しました。次の回避策は、親のプロパティを拡張しますが、親の_set_ageメソッドを直接呼び出して拡張します。しわは常に正しいはずです。それは少しjavathonicです。
import threading
class Foo(object):
def __init__(self):
self._age = 0
def _get_age(self):
return self._age
def _set_age(self, age):
self._age = age
age = property(_get_age, _set_age)
class ThreadsafeFoo(Foo):
def __init__(self):
super(ThreadsafeFoo, self).__init__()
self.__lock = threading.Lock()
self.wrinkled = False
def _get_age(self):
with self.__lock:
return super(ThreadsafeFoo, self).age
def _set_age(self, value):
with self.__lock:
self.wrinkled = True if value > 40 else False
super(ThreadsafeFoo, self)._set_age(value)
age = property(_get_age, _set_age)
class Foo:
# Template method
@property
def age(self):
return self.dothis()
# Hook method of TM is accessor method of property at here
def dothis(self):
return 11
class Bar(Foo):
def dothis(self):
return 44
Nizam Mohamedと同じですが、テンプレートメソッドとプロパティの両方を使用して スタイルガイド 2.13.4