はじめに
Python には @property というデコレータが用意されており、これを使うことで(擬似的に)プライベートなインスタンス変数に対する getter/setter のようなメソッドを作成する事ができます。
本頁では、Pythonの @property デコレータについて以下の内容を説明します。
- @property デコレータの使い方(getter/setter)
- @property デコレータを使ってプライベート変数を実現
- @property デコレータを使う利点
本内容は、以下「Effective Python」でも紹介しています。
@property デコレータの使い方(getter/setter)
- 必ず getter/setter 経由でインスタンス変数にアクセスさせる
- インスタンス変数の参照は許可、書換えは禁止させる
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
class MyTest(): def __init__(self): # インスタンス変数の prefix に __ を付けて定義 # これにより __prop がマングリングされて参照不可 self.__prop = "Python" # この関数名は既存のインスタンス変数名と重複不可 @property def prop(self): print("getter") return self.__prop # setter より前に同名の getter の定義が必要 # setter が無い場合、__prop は読み取り専用になる @prop.setter def prop(self, val): print("setter") self.__prop = val obj = MyTest() print(obj.prop) # getter # Python obj.prop = "pip" # setter print(obj.prop) # getter # pip |
ポイント
- インスタンス変数の prefix(接頭語)に __ (アンダーバー2個)を付ける
- @property デコレータを付けた getter メソッドを定義
- setter メソッドを定義しない場合は、読み取り専用になる
@property デコレータを使ってプライベート変数を実現
上記の例で記述した Python プログラムから、@prop.setter のメソッドを削除します。
すると、書換えしようとすると「AttributeError」の例外が発生します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
class MyTest(): def __init__(self): self._prop = "Python" @property def prop(self): print("getter") return self._prop obj = MyTest() print(obj.prop) # getter # Python obj.prop = "pip" # AttributeError: can't set attribute |
@property デコレータを使う利点
Python の @property デコレータを使う利点は、ずばり以下です。
- インスタンス変数ごとに getter/setter を用意しなくてよい
⇒参照・書換えの際にメソッドを呼ばなくてよいので可動性UP - インスタンス変数の参照・書換えの際に後から条件を追加できる
⇒再利用性を向上できる(他のプロジェクト等で利用できる)