モブプロな人たちのブログ

Web サービス開発しているエンジニアの日記です。Python 大好き Flask 大好き。たまに Swift で iOS ゲーム開発も。

Python で get や set メソッドよりも素のままの属性を使う

「Effective Python」を久しぶりに読み返して、当時は特に何も思わなかった箇所に引っかかったのでメモを残しておきますシリーズ第7弾。

Effective Python ―Pythonプログラムを改良する59項目

Effective Python ―Pythonプログラムを改良する59項目

Python で get や set メソッドよりも素のままの属性を使う

他の言語から Python に移ってきたプログラマは、ごく自然にクラスの中でゲッターやセッターメソッドを明示的に実装しようとする

ふむふむ、なるほど。確かに昔 Java を勉強してた時、ゲッターとかセッターとかちょくちょく書いてました。

class User1:
    def __init__(self, age):
        self.age = age

    def get_age(self):
        return self._age

    def set_age(self, age):
        self._age = age


if __name__ == '__main__':
    user1 = User1(30)
    user1.set_age(user1.get_age() + 1)

↑こんな感じのやつです。

ただ、見てわかる通り、age に 1 を足したいだけなのに、やけにゴチャゴチャした感じになってますね。

こういうのは「Python 流ではない」みたいです。

では、どうするかというと、

class User2:
    def __init__(self, age):
        self.age = age


if __name__ == '__main__':
    user2 = User2(30)
    user2.age += 1

まあ簡単。

いや、ふざけてないです。本当に必要なのか考えずに、おまじない的にゲッターやセッターを書くのはやめましょうという話ですね。

さて、しばらくして特別な振る舞いが必要になった時どうすれば良いんでしょうか?

例えば、年齢は200歳まで許容するが、それ以上は例外処理にしたい場合、

class User3:
    def __init__(self, age):
        self.age = age

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, age):
        if age > 200:
            raise ValueError('age must be <= 200')
        self._age = age


if __name__ == '__main__':
    user3 = User3(30)
    user3.age += 1

    user3.age += 170
    # ValueError: age must be <= 200

デコレータを付けました。これで OK です。