▶ クラスについて基本から学びたい方は以下の投稿をどうぞ
はじめに
本ブログでのクラスの学習もだいぶ進んできましたね。今回はプロパティについて基本から解説をしてきます。「プロパティとは」から説明を始めて、組み込み関数であるプロパティ関数によるgetter, setterの定義、「@property」デコレータや「@メソッド名.setter」デコレータによる設定まで解説をしていきます。
プロパティとは
プロパティは、値をしっかり管理したいけどインスタンス変数のように自然に値にアクセスしたい場合に使います。「クラスの外部からはインスタンス変数のように使用でき、クラス内部ではメソッドのように実装した属性のこと」です。
つまり、インスタンス変数にアクセスする際に、内部的にはメソッドを通した処理をしてくれる仕組みです。普通に値を取ってきているように見せて、裏ではメソッドを動かす、普通に値をセットしているように見せて、裏ではメソッドを動かす、ということですね。このようにすることで、たとえば値をセットするときであれば、メソッド内にvalidationチェックを入れる、ということもできますね。
プロパティには、値を取得するためのgetter(ゲッター)
、値をセットするためのsetter(セッター)
、値を削除するためのdeleter(デリーター)
があります。
プロパティを実装する
プロパティを設定するには組み込み関数のproperty関数を使う方法と、デコレータを使う方法((「@property」デコレータや「@メソッド名.setter」デコレータ)など)があります。順にみていきましょう。
property()を使う
最初に書式を確認しておきましょう。次のような書式で定義することができます。
fgetにはプロパティの値を読みだすためのメソッド、fsetにはプロパティの値を設定するためのメソッド、fdelにはプロパティの値を削除するためのメソッド、docにはプロパティのヘルプ文字列(docstring)を指定します。
__init__内で定義するインスタンス変数は「_(アンダースコア)」を付けた変数名とする必要があるので、注意が必要です。
実際にこの動きをgetter, setter で確認しましょう。
class Animal():
def __init__(self,name):
self._name = name
def get_name(self):
print('getterでデータを取得しています')
return self._name
def set_name(self,new_name):
print('setterでデータを書き換えています')
self._name=new_name
name = property(get_name,set_name)
Animalクラスを作成しました。今回はインスタンス変数はnameのみです。ここでは、このnameにgetter, setterを設定したいので、アンダースコアを付けた変数名「_name」とします。(3行目)
5-7行目でgetterメソッドを定義しています。このメソッドが呼ばれたことが確認できるように6行目にprint文を入れています。このメソッドは「_name」属性を読みだすだけのメソッドです。
9-11行目でsetterメソッドを定義しています。このメソッドも呼ばれたことが確認できるように10行目にprint文を入れています。このメソッドは引数「new_name」をとり、「_name」の値を書き換えます。
13行目でproperty関数を使って、get_nameメソッドをgetter(第一引数fget)、set_nameメソッドをsetter(第二引数fset)の設定をしています。
では、インスタンスを一つ作って、インスタンス変数の値を見てみることにしましょう。
# インスタンスの作成
rakuda=Animal('rakuda')
# nameを取得
rakuda.name
まずrakudaというインスタンスを作成して、その後、このインスタンスの属性nameを取得しています。すると、「getterでデータを取得しています」が表示されて、その後に「rakuda」という値が表示されています。値の取得に「get_name」メソッドが使われていることがわかりますね。
同様にsetterについても見てみましょう。
# nameの書き換え
rakuda.name='らくだ'
普通にname属性を読んで書き換えているように見えますが、結果を見ると「setterでデータを書き換えています」と表示されているので、「set_name」メソッドが呼ばれたことがわかりますね。念のため、値が書き換わっているのかを確認してみましょう。
# nameの確認
rakuda.name
getterが呼ばれて、その後に「らくだ」が返ってきました。値がちゃんと書き換わっていますね。
デコレータを使う
同じことがデコレータを使って書くこともできます。getterには「@propery」デコレータで修飾します。setterはgetterと同じ名前のメソッドとして、「@メソッド名.setter」というデコレータで修飾します。
class Animal():
def __init__(self,name):
self._name = name
@property
def name(self):
print('getterでデータを取得しています')
return self._name
@name.setter
def name(self,new_name):
print('setterでデータを書き換えています')
self._name=new_name
今回はgetter, setterのメソッド名は「name」としています。getterには「@propery」デコレータ、setterには「@name.setter」デコレータで修飾しています。
先ほどと同じように試してみましょう。まず、name属性の確認です。
# インスタンスの作成
rakuda=Animal('rakuda')
# nameを取得
rakuda.name
先ほどと同じように普通にname属性にアクセスすると、裏側でメソッドが走っているのがわかりますね。同様にsetterについても確認しておきましょう。
# nameの書き換え
rakuda.name='らくだ'
setterが動いていることが確認できました。念のため値を見ておきましょう。
# nameの確認
rakuda.name
再び、getterが呼ばれて値を取ってきています。「らくだ」に書き換わっていることが確認できました。
まとめ
今回はプロパティについて扱いました。プロパティは外からインスタンス変数に不通にアクセスすると、裏側ではメソッドが呼ばれて値を返したり、書き換えたりする仕組みを構築するための仕組みです。その設定方法には2種類あり、一つは組み込み関数であるproperty関数を使う方法、もう一つはデコレータを使う方法です。
クラス内ではアンダースコアを付けた名称のインスタンス変数(今回の例では「_name」)とすることに注意するようにしてください。
またデコレータを使って設定する場合は、getter, setterのメソッド名は同じ名前にする、ということも忘れないようにしましょう。
コメント