PUROGU LADESU

ポエムがメインのブログです。

【Python】メソッド内でのクラス変数の注意点

インスタンスメソッドからクラス変数を利用する

クラス変数はインスタンスメソッドから利用する場合混乱しやすいため注意が必要。

selfでアクセスする場合、インスタンス変数 -> クラス変数の順で探しに行くため、
クラス変数しかない状態でselfで代入すると、インスタンス変数が作成されてしまい、
以降selfではインスタンス変数にアクセスすることになってしまう。

class Person(object):
    # クラス変数
    count = 1

    def __init__(self, age=8):
        # インスタンス変数
        self.__age = age
    
    def add_count(self):
        # 参照は構わないが、ややこしい可能性あり
        print(self.count)
        # これをするとインスタンス変数になってしまう
        self.count += 1
        # 以下のどれかにする
        Person.count += 1
        # __class__.count += 1
        # type(self).count += 1
        print(self.count)
        print(Person.count)

    # クラスメソッド(clsでクラス変数にアクセス)
    @classmethod
    def get_cls_count(cls):
        return cls.count


これを避けるには以下のどれかの方法でクラス変数にアクセス(更新)する。
参照だけならselfでも問題ないが、可読性や取り違え防止を考えると参照時も統一したほうが良いかもしれない。
見た目のわかりやすさから言うと__class__がいいように思う。

Person.count += 1
__class__.count += 1
type(self).count += 1


[Python入門]クラス変数/クラスメソッド/スタティックメソッド:Python入門(1/2 ページ) - @IT

クラスメソッド内からクラス変数にアクセスする

クラスメソッドからはclsでアクセスする。
ちなみにclsは慣例であって別の名前でも問題ない。

そもそもの話として

そもそもインスタンスメソッドからクラス変数をアレコレ更新する、というのがそもそも設計として良くないとは思われるが、
使いたくなる場面は出てくるだろう。