@property
について語るには、基礎から語らなきゃいけないんです。
学校の例を見てみましょう。学生というクラスがあるとしましょう。
通常、クラスの属性を決めるときに、属性をそのまま公開しても良いのですが、勝手に変更することが可能となり、あまりおすすめできません。というのも、点数は通常0 ~ 100の範囲内に位置するので、デタラメに9999にもできてしまいます。明らかにおかしいですね。
s = Student() #オブジェクト作成
s.score = 9999
s.score = 1111
# 勝手に書き換えられる
ということで、set_score()
やget_score()
で成績を取得することにしました。(普通の流れです)
class Student:
def get_score():
return self.self._score
def set_score(self, value):
if not isinstance(value, int):
raise ValueError("score must be an integer! ")
if value < 0 or value > 100:
raise ValueError("score must be between 0 ~ 100!")
self._score = value
これでもう勝手に属性を書き換えられなくなったんだね。点数は0 ~ 100の範囲じゃなきゃだめだとと制限をかけることができました。
>>> s = Student()
>>> s.set_score(60) # ok!
>>> s.get_score()
60
>>> s.set_score(9999)
Traceback (most recent call last):
...
ValueError: score must between 0 ~ 100!
しかし、これは少し複雑さを増したようなきがするんだ。なんかここでズルをしたくなって、get, setみたいな複雑な方法ではなく、普通に属性を呼びたい、また、勝手に書き換えもできないような方法はないの???って知りたくなった。
あるよ。それは@property
class Student:
@property
def score(self):
return self._score
@score.setter
def score(self, value):
if not isinstance(value, int):
raise ValueError("score must be an integer!")
if value < 0 or value > 100:
raise ValueError("score must be between 0 ~ 100!")
self._score = value
@property
は少し複雑なので、中身の説明は割愛します。まずは使えるようにしよう。getter
の方法を属性にしたいときに、@property
を足せばいい。@property
がもう一個のデコレーター@score.setter
を作成した。これを持ってsetter方法を属性のようにします。
getter -> @property
setter -> 属性.setter
>>> s = Student()
>>> s.score = 60 # OK 実際はre(60)
>>> s.score # OK 実際はs.get_score()
60
>>> s.score = 9999
Traceback (most recent call last):
...
ValueError: score must between 0 ~ 100!
# 自分で定義したエラーメッセージ
read onlyの属性を定義することも可能→getterメソッドだけ定義し、setterメソッドを定義しなければread onlyですよ。
class Student(object):
@property
def birth(self):
return self._birth
@birth.setter
def birth(self, value):
self._birth = value
@property
def age(self):
return 2014 - self._birth
# birthは書き換えも読み込みもできるが、ageは読み込みのみできる。
さいごに
@property
はクラスの定義においてよく使われているので、使えるようにしましょう。私も実はブロックチェーンの練習で@property
に出会って思い出すために、ここでメモっておきました。
さてさてまたね。