今回は、Pythonでのプロパティの実装方法を解説します。
プロパティとは?
ここで取り扱うプロパティとは、クラス利用者がそのメンバ変数にアクセスするときにgetterやsetterを意識することなくアクセス出来るようにする仕組みです。
通常、クラスを実装するときはメンバ変数を直接外部に公開せず、プライベートにしつつ、別途getterとsetterを用意します。これをカプセル化と呼びます。よって、クラス利用者はgetterやsetterを介してメンバ変数にアクセスします。
class Name1: def __init__(self): self._firstname = '' self._lastname = '' def get_firstname(self): return self._firstname def set_firstname(self, firstname): self._firstname = firstname def get_lastname(self): return self._lastname def set_lastname(self, lastname): self._lastname = lastname def get_fullname(self): return self._firstname + self._lastname name = Name1() name.set_firstname('Fugataro') name.set_lastname('Hogemoto') print(name.get_firstname()) print(name.get_lastname()) print(name.get_fullname()) # Fugataro # Hogemoto # FugataroHogemoto
しかし、プロパティを用いることで、カプセル化を維持しつつ、クラス利用者はgetterやsetterを意識することなくメンバ変数にアクセス出来るようになります。
Pythonでプロパティを実装する方法は2通りあるため、両方解説していきます。
property関数を用いる方法
1つ目はproperty関数を用いる方法です。
まず、今まで通りにgetterとsetterを宣言します。そして、property関数に先ほど宣言したgetterとsetterの関数名を渡します。こうすることにより、クラス利用者はインスタンス名.メンバ変数名
のフォーマットでメンバ変数にアクセス出来るようになりつつ、クラス内部では、先ほどproperty関数に渡したgetterとsetterを経由して、メンバ変数の受け渡しが行われます。
class Name2: def __init__(self): self._firstname = '' self._lastname = '' def get_firstname(self): return self._firstname def set_firstname(self, firstname): self._firstname = firstname def del_firstname(self): del self._firstname firstname = property( get_firstname, set_firstname, del_firstname ) def get_lastname(self): return self._lastname def set_lastname(self, lastname): self._lastname = lastname def del_lastname(self): del self._lastname lastname = property( get_lastname, set_lastname, del_lastname ) def get_fullname(self): return self._firstname + self._lastname fullname = property(get_fullname) name = Name2() name.firstname = 'Fugataro' name.lastname = 'Hogemoto' print(name.firstname) print(name.lastname) print(name.fullname) # Fugataro # Hogemoto # FugataroHogemoto
また、メンバ変数をdel
する関数も登録することが出来ます。以下サンプルソースでは実際にメンバ変数をdel
していますが、del
した後にそのメンバ変数にアクセスすると例外が発生するため、del
が正常に機能していることがわかります。
name = Name2() name.firstname = 'Fugataro' print(name.firstname) del name.firstname print(name.firstname) # Fugataro # AttributeError: 'Name2' object has no attribute '_firstname'
デコレータを用いる方法
2つ目はデコレータを用いる方法です。
デコレータを用いる場合も、getter、setter、deleterを宣言しますが、それら関数に、@property
、@メンバ変数名.setter
、@メンバ変数名.deleter
を付与するだけです。
class Name3: def __init__(self): self._firstname = '' self._lastname = '' @property def firstname(self): return self._firstname @firstname.setter def firstname(self, firstname): self._firstname = firstname @firstname.deleter def firstname(self): del self._firstname @property def lastname(self): return self._lastname @lastname.setter def lastname(self, lastname): self._lastname = lastname @lastname.deleter def lastname(self): del self._lastname @property def fullname(self): return self._firstname + self._lastname name = Name3() name.firstname = 'Fugataro' name.lastname = 'Hogemoto' print(name.firstname) print(name.lastname) print(name.fullname) # Fugataro # Hogemoto # FugataroHogemoto
name = Name3() name.firstname = 'Fugataro' print(name.firstname) del name.firstname print(name.firstname) # Fugataro # AttributeError: 'Name3' object has no attribute '_firstname'