[Python] クラスメソッドと静的メソッド

今まで、Python でのクラスメソッド、静的メソッドを意識したことがなかったので、備忘録です。

Difference between staticmethod and classmethod

  • 静的メソッドはクラスの外に定義されている関数と同じ。確たる理由がなければわざわざ使う必要はない。
  • 特に継承時の動作に違いが出る。

以下のようなファイルをclass_ex.pyとして保存します。

class HelloMethod():
    # クラス変数
    a = 'class_var'
    
    def __init__(self):
        # インスタンス変数
        self.b = 'instance_var'

    def instance_method_a(self):
        return HelloMethod.a 
    
    def instance_method_b(self):
        return self.b

    @classmethod
    def class_method_a(cls):
        return cls.a 
    
    # 当然ながら動かない。
    # @classmethod
    # def class_method_a(cls):
    #     return self.b

    @staticmethod
    def static_method_a():
        return HelloMethod.a

class HelloMethodChild(HelloMethod):
    a = 'class_var_of_child'

インタラクティブモードを起動して読み込んでおきます。

>>> import class_ex

インスタンスメソッド

インスタンスから呼び出すメソッドです。

当然のことながら、インスタンスを作ってから呼び出します。

また慣習的に仮引数にselfを持ちます。

>>> hello_method = class_ex.HelloMethod()
>>> hello_method.instance_method_a()
'class_var'
>>> print(hello_method.instance_method_b())
instance_var

クラスメソッド

インスタンスメソッドとは違い、インスタンスを作らずともクラスから呼び出すことのできるメソッドです。

@classmethodをデコレーターにして、慣習的に仮引数にclsを持ちます。

>>> print(class_ex.HelloMethod.class_method_a())
class_var

静的メソッド

クラスメソッドと同じく、インスタンスを作らずとも呼び出すことができるメソッドです。

@staticmethodをデコレーターにします。

>>> print(class_ex.HelloMethod.static_method_a())
class_var

クラスメソッドと静的メソッドの動作の違い

継承をしたときに、クラスメソッドと静的メソッドでは動作の違いが出ます。

# 子クラスのクラス変数を参照する
>>> print(class_ex.HelloMethodChild.class_method_a())
class_var_of_child
# 親クラスのクラス変数を参照する
>>> print(class_ex.HelloMethodChild.static_method_a())
class_var

継承先のクラスから呼び出したときに、クラスメソッドは継承先の子クラスのクラス変数を参照しますが、静的メソッドは継承元の親クラスのクラス変数を参照します。