decoratorを用いた以下のようなコードを考える。
class Circle:
def __init__(self, radius):
self._radius = radius
@property
def radius(self):
"""The radius property."""
print("Get radius")
return self._radius
@radius.setter
def radius(self, value):
print("Set radius")
self._radius = value
@radius.deleter
def radius(self):
print("Delete radius")
del self._radius
このとき、getter, setter, deleterはそれぞれ実体としては違う関数であるにも関わらず、なぜ同じradiusという名前をdefのあとに記載するのか。
違うものを定義しているなら、たとえばあとの2つはradius_set, radius_delとすべきではないのか?(結論を先取りして言うと、上記の例のように同じ名前で書く方が自然で普通であって、このように名付け分けるべきではない。)
事実として、これは実際のメソッドの名前ではない
表題のとおりだが、ここで定義しているプロパティradius(正確にはCircle.radius)は、propertyオブジェクトの一つのインスタンスであり、これはgetter, setter, deleterとしてメソッドCircle.radius.fget, Circle.radius.fset, Circle.radius.fdelを持つ。(このことはdir(Circle.radius)としてみればわかる。
これらの名前は上記のとおりであって、radiusという名前ではない。ここでdef radius(self, value)とかdef radius(self)とか言っているが、これらは言わば仮の名前であって、getterやsetterのオブジェクトの名前として直接使われるわけではないのだ。
(一方、@propertyの直後のdef radius(self)にあらわれる"radius"はプロパティの名前として使われる。ただしここでも、関数定義ブロックで定義しているのはgetterとして用いる関数だが、radiusはそのgetter関数の名前ではなく、プロパティの名前に使われるだけである。)
事実として、どのような名前を使っても同じように動く
以下のように書いても、定義としてはまったく同じことである:
(以下は推奨されない例ではあるが文法的には問題ない)
# 推奨されない例
class Circle:
def __init__(self, radius):
self._radius = radius
@property
def radius(self):
"""The radius property."""
print("Get radius")
return self._radius
@radius.setter
def radius_set(self, value):
print("Set radius")
self._radius = value
@radius.deleter
def radius_del(self):
print("Delete radius")
del self._radius
ではなぜこのように名付け分ける方が不自然で、同じ名前の下に記述する方が自然なのか。
慣習、文化として、同じ名前を使う方が自然である
名付け分けるのは冗長である
これらのsetter, deleterがそれらであることは、@radius.setter, @radius.deleterというdecoratorによって示されている。これらの違いをdefのあとの名前によっても示すことは、同じことを重複して説明することになり、冗長である。
これらが同じプロパティに対して設定されたsetter, deleterであることがひと目で分かる
表題のとおり。
また、setter, deleterを定義する際(そもそも定義する必要があるとして)、新しい別の関数を設定しているというよりは、お気持ちとしては1つのpropertyを設定しているにすぎない。この点からも同じ名前をつけることは自然である。
結局、深く悩まないこと
結局のところ、
@radius.setter
def hoge:
のhogeは、名前ではない(名前空間にない)。こだわっても仕方がないことに深く悩まないことも生きるスキルの1つだ。