見出し画像

Pythonのpropertyを知ろう

こんにちは
記事書くのに疲れてずっと書いていなかったのですが、また少しずつ更新していこうと思いました。
この少しずつが、誰かの役に立ったら良いなと思っています。

今回はPythonのpropertyについて少し。

propertyとは

Pythonのpropertyは、簡単に言うとクラスの属性の使い勝手がとてもよくなる関数(デコレーター)です。
例えばですが、よくある例えで言うと「人間クラス」があってその属性として名前・年齢・性別・身長・体重があったとします。
それを単純にコードにすると以下のようになると思います。

class Human:
    def __init__(self, name, age, sex, height, weight):
        self.name = name
        self.age = age
        self.sex = sex
        self.height = height
        self.weight = weight

メソッドが無いのは、とりあえず説明の簡略化の為にそうしています。
コード中のself.〇〇が属性ですよね。

ここでHumanクラスをインスタンス化して、属性をいじった場合、現状のままだとどんな値でも入れられるようになってしまっている、というのは分かると思います。

この状態は、あまり良くありません。
何が良く無いのか?それは

どんな場面においても、どんな条件下においてもその属性(インスタンス変数)を変更する事が可能な事です。

例えばの話

ひとつ例え話ですが、会社で健康診断をしていて身長と体重を測定したとします。
この時に検査の結果を、検査の担当の方が記録紙に記入すると思います。
検査した結果が気に入らなかったあなたは、記録紙に記入してある身長と体重を書き換えてしまいました。

一度でもその書き換えが出来ると分かったあなたは毎年のように書き換えてしまいます。自分の身体の現実から目を背けていますね。

そして数年経ったある日あなたは病院で「糖尿病」だと診断されます。
何故なのか、それは数年間も健康診断の内容を書き換えていたからに他なりません。
実測した身長と体重から割り出されるはずであった体脂肪率も実際は肥満という判定だったにも関わらず、書き換えてしまっていた事によって肥満にはならず、スルーされていたのです。
その結果、生活習慣病が悪化してしまい、糖尿病を患ってしまった。

といったように(無理矢理感ハンパない)、いつでもどんな条件でも値を書き換える事ができる状態だと、その後に待っているかもしれない病気(プログラムで言うとエラー等)を引き起こす原因になりかねないということが分かったと思います。

じゃあどうするのか

ここでpropertyの登場です。
先ほどのHumanクラスで言うと基本的に名前なんて一度決まれば変更する事は無いと思います。
なのでこれをマングリングという手法 + propertyデコレーターを使って実質的に変更不能にしてやりましょう。

class Human:
    def __init__(self, name, age, sex, height, weight):
        self.__name = name
        self.age = age
        self.sex = sex
        self.height = height
        self.weight = weight

    @property
    def name(self):
        return self.__name

Humanクラスの初期化処理の部分をself.__nameに変更しました。(マングリング)
このアンダーバーを2つ繋げて書くと、その属性はクラス外から通常の「インスタンス.__name」という方法では参照出来ないようになります。(実際は参照する方法は有ります…)

変更してほしくないからこのようにしましたが、クラス外からデータを参照出来ないようでは意味がありません。そこでpropertyを使います。

@propertyと書いてその下にメソッド定義を書くと、そのメソッド名がそのまま属性として扱えるようになります。
return文で返しているデータが属性値として参照元に与えられます。
ちょっと意味わからないと思うので詳しく見ていきましょう。

Humanクラスの属性で名前を表しているのはself.__nameでしたね。ですがクラス以外から「インスタンス.__name」で参照する事は出来ません。

そしてpropertyデコレーターを使ってnameという名前のメソッドを定義しました。これが属性として有効になるので、クラス外からは「インスタンス.name」で名前のデータを参照する事ができるようになります。
そして、「インスタンス.name = 新しい名前」とするとエラーになります。外部から参照はできるが、変更は出来ないということです。

class Human:
    def __init__(self, name, age, sex, height, weight):
        self.__name = name
        self.age = age
        self.sex = sex
        self.height = height
        self.weight = weight

    @property
    def name(self):
        return self.__name

human = Human("青木"19"男"16656)
print(human.name) #output -> 青木
human.name = "田中" #error

これの何が良いのか。
それは、クラスの外部からは「参照のみ有効」になるからです。これで先ほどの健康診断の例でやってしまっていた「外部からのデータの書き換え」が出来なくなったわけです。

初期化処理でデータがセットされたらその後は基本的に参照のみ可能で、変更はできなくなります。
(そのデータを変更するメソッドをHumanクラスに作成すれば変更は可能ですが)

健康診断の例で言うと、担当者が身長と体重を記入したらそれ以外の人間は、そのデータを見るしか出来ないということ。鉛筆ではなくボールペンで書かれたみたいなものですね。

まとめ的なやつ

今回はPythonのpropertyを身近な例を交えて簡単に説明しました。

そのpropertyで定義された属性値を変更するためのデコレーターもあるので、また追々記事を書いていこうと思います。

最後まで読んでくれてありがとうございました。

この記事が気に入ったらサポートをしてみませんか?