初心者データサイエンティストの備忘録

調べたことは全部ここに書いて自分の辞書を作る

Pythonの@propertyの振る舞い

Pythonで@propertyがよくわからなかったので、色々調べてみた。
正直、完璧に理解した感はないが、一旦分かった範囲でまとめてみる。

@propertyとは?

3.4. プロパティ - ゼロから学ぶ Python」よると、@propertyを下記のように説明している。

クラスのメンバで変数のように参照することのできる関数のことをプロパティといいます

ということで、ごく簡単なスクリプトを書いて確認してみる。

class Test:
    def __init__(self, a):
        self._a = a
        
    @property
    def a(self):
        return self._a
    
    def func1(self):
        return self.a

test = Test(a=1)
print(test.func1())

# -> 1 が表示される

func1の中でメソッドaをself.aで呼び出していることがポイント。本来、aはメソッドなので、カッコをつけたself.a()として呼び出す必要がある。しかし、@propertyのお陰で変数のような形式で呼び出すことができている。

@propertyを使う場面

オブジェクト指向設計実践ガイド(下記の本)によれば、すべてのインスタンス変数は隠蔽すべきとのこと。 したがって、変数を直接扱うのではなく、メソッドaをはさみ、隠蔽することが必要だ。その際、@propertyを設定することで、a()ではなくa単体を書けばよいのでコードが少しシンプルになるということらしい。

注意

上記と似たようなコードだが、下記は動かない。

class Test:
    def __init__(self, a):
        self.a = a # 変数aに_がなくなった
        
    @property
    def a(self):
        return self.a
    
    def func1(self):
        return self.a

test = Test(a=1)
print(test.func1())

# エラー:can't set attributeを出力する

これは、変数aとメソッドaの名前が同じだからエラー:can't set attributeを出力してしまう。
なので、propertyを使うときは、必ず_を前に一つつけた変数を用意しましょう。
※_を前にひとつつけた変数は、慣習的にそのクラスの外では使わない変数を指すようです。