あまり良くない書き方 その3 getter/setter

他のオブジェクト指向プログラム言語、特にJavaようにカプセル化を是とする言語をメインで経験された方は、クラスのメンバにアクセスするためのgetter、setterメソッドを実装してしまいがちですが、pythonではどのように実装するのが望ましいのでしょうか。

getter/setter

冒頭で書いたとおり、Javaを経験された方はクラスに以下のようなコードを書いてしまうのではないでしょうか?(実際、私がそうでした。)

class User:
    
    def __init__(self, name):
        self.name = name
        self.age = None

    def get_name(self):
        return self.name

    def set_name(self, name):
        self.name = name

    def get_age(self):
        return self.age

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

ですが、pythonではこのような書き方はあまりしません。というのも、そもそも厳密な意味でのメンバの隠蔽が言語仕様としてできないためあまり意味がありません。pythonでは公開されたメンバに対して直接アクセスします。

class User:
    
    def __init__(self, name):
        self.name = name
        self.age = None

if __name__ == '__main__':
    user = User('kuro')
    
    # 利用側はドットで直接アクセスします。
    user.age = 19
    print(user.name + "さんは" + str(user.age) + "歳です")

また、メンバアクセス時に何らかの処理を加えたい場合は、プロパティを活用しましょう。これによりアクセスを制限したり、不正な値を排除することが可能となります。(プロパティについてはこちらをご参照ください。)

例えば、上のサンプルでageに値を設定ときに0以上の整数を使わせたい場合、以下のように記述します。

class User:
    
    def __init__(self, name):
        self.name = name
        self.__age = None

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

    @age.setter
    def age(self, age):
        if type(age) == int:
            if age > 0:
                self.__age = age
                return

        raise ValuError('年齢は0以上の整数を指定してください')

変更させたくない場合は、問答無用でsetter内で例外を起こすのも1つの手でですね。