次の例は、基底クラスFooのgetterプロパティxに派生クラスでsetterを追加する方法です。
class Foo:
def __init__(self):
self._x = "I'm Foo.x"
@property
def x(self):
return self._x
class Bar(Foo):
@Foo.x.setter
def x(self, value):
self._x = value
実行すると、次のようになります。
>>> b = Bar()
>>> b.x
"I'm Foo.x"
>>> b.x = "I'm Bar.x"
>>> b.x
"I'm Bar.x"
さらに、deleterを追加する場合は、次のように書きます。
class Foo:
def __init__(self):
self._x = "I'm Foo.x"
@property
def x(self):
return self._x
class Bar(Foo):
@Foo.x.setter
def x(self, value):
self._x = value
@x.deleter
def x(self):
self._x = "Nothing"
実行すると下記のようになります。
>>> b = Bar()
>>> b.x
"I'm Foo.x"
>>> b.x = "I'm Bar.x"
>>> b.x
"I'm Bar.x"
>>> del b.x
'Nothing'
最後のデコレータは、@Foo.x.deleterではなく、@x.deleterである点が注意です。
@Foo.x.deleterとすると、setterが無いプロパティが生成されてしまいます。その理由は以下です。
setterのデコレータにあるFoo.xは、propertyオブジェクトです。Foo.xは、getterしか持っていません。
propertyオブジェクトのsetterメソッドは、引数の関数をsetterに追加した新たなpropertyオブジェクトを返します。つまり、Barの@Foo.x.setterデコレータで始まる定義で、Bar.xにはgetterとsetterを持つpropertyオブジェクトが生成されBar.xに代入されています。
propertyオブジェクトの、deleterメソッドは、引数の関数をdeleterに追加した新たなpropertyオブジェクトを返します。@Foo.x.setterデコレータで始まる定義で、Bar.xにはgetterとsetterを持つpropertyオブジェクトが生成され代入されているので、@x.deleterとすると、getterとsetterに加え、deleterが追加されます。(@Foo.x.deleterとするとsetterを持たないFoo.xから新しいプロパティオブジェクトを生成することになるので、@Foo.x.setterで作成したsetterを持つプロパティオブジェクトを上書きしてしまいます。)
(setterとdeleterの定義の順番が逆の場合、逆に@Foo.x.deleterと@x.setterとする必要があります。)
参考