Masayan tech blog.

  1. ブログ記事一覧>
  2. Pythonのインスタンスメソッド、クラスメソッド、スタティックメソッドの使い分け

Pythonのインスタンスメソッド、クラスメソッド、スタティックメソッドの使い分け

公開日

この記事を読むとできるようになること

  • Pythonのインスタンスメソッド、クラスメソッド、スタティックメソッドの概要、特徴が理解できる
  • Pythonのインスタンスメソッド、クラスメソッド、スタティックメソッドの使い分けができる

定義方法

まずはコード例

class MyClass:
    def instance_method(self):
        print("インスタンスメソッド")

    @classmethod
    def class_method(cls):
        print("クラスメソッド")

    @staticmethod
    def static_method():
        print("スタティックメソッド")

インスタンスメソッド

  • 特にデコレーター不要
  • selfを引数に受け取る(self=生成されたインスタンス自身)

クラスメソッド

  • @classmethodデコレーター
  • clsを引数に受け取る(cls=このクラス自身)

スタティックメソッド

使い分け

インスタンスメソッド

ポリモーフィズムをガンガン活用して行きたい場合はインスタンスメソッド(複雑な機能要件、パターンが多く各具象クラスごとに異なる振る舞いをさせたい場合など。つまりif文で条件分岐が激しい時など)

class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        pass  # 子クラスでオーバーライド

class Dog(Animal):
    def speak(self):
        print("Woof!")

class Cat(Animal):
    def speak(self):
        print("Meow!")

# さまざまな動物のリスト
animals = [Dog("ポチ"), Cat("タマ"), Dog("ポチ太郎")]

# すべての動物に同じメソッドを呼び出す
for animal in animals:
    animal.speak()

クラスメソッド

クラス変数はクラス全体で共有される値なので、どのインスタンからも同じ値を参照したい定数などを扱うとき。クラス名を使って条件分岐を行うなど、クラス名自体をパラメータとして利用するような処理。

つまり、全てのクラスで共有した値(状態)を持たせたい場合

class Counter:
    count = 0

    @classmethod
    def increment(cls):
        cls.count += 1

    @classmethod
    def get_count(cls):
        return cls.count

# クラスメソッドを呼び出す
Counter.increment()
Counter.increment()
print(Counter.get_count())  # 出力: 2

状態を持たせるが、どのインスタンスからも同じ定数を参照させたい場合

class Counter:
    MAX_COUNT = 100  # 最大カウント値

    def __init__(self):
        self.count = 0

    def increment(self):
        if self.count < self.MAX_COUNT:
            self.count += 1

    def get_count(self):
        return self.count

スタティックメソッド

クラス変数、インスタンス変数を使用しないファクトリーメソッド。または、日付け処理などユーティリティメソッドはスタティックメソッドなど。あるいは、元々単純な関数として作成していたが、ある程度まとまりでグルーピングしたい時など

import datetime

class DateUtils:
    @staticmethod
    def is_weekday(date):
        """指定された日付が平日かどうかを判定します。"""
        return date.weekday() < 5

    @staticmethod
    def get_first_day_of_month(year, month):
        """指定された年月の一日のdatetimeオブジェクトを返します。"""
        return datetime.date(year, month, 1)

    @staticmethod
    def get_last_day_of_month(year, month):
        """指定された年月の一か月の最終日のdatetimeオブジェクトを返します。"""
        return datetime.date(year, month, 1) + datetime.timedelta(days=32) - datetime.timedelta(days=32.day)

    @staticmethod
    def format_date(date, format_str="%Y-%m-%d"):
        """指定された日付をフォーマットされた文字列に変換します。"""
        return date.strftime(format_str)

特徴

コード例からそれぞれの特徴を以下に記載

class MyClass:
    def instance_method(self):
        print("インスタンスメソッド")

    @classmethod
    def class_method(cls):
        print("クラスメソッド")

    @staticmethod
    def static_method():
        print("スタティックメソッド")

呼び出しに、インスタンスの生成を必要とするか

インスタンスメソッド

必要

クラスメソッド

不要

スタティックメソッド

不要

# インスタンスを作成
obj = MyClass()

# 各メソッドを呼び出す
obj.instance_method()  # インスタンスメソッドを呼び出す
MyClass.class_method()  # クラスメソッドを呼び出す
MyClass.static_method()  # スタティックメソッドを呼び出す

暗黙的な引数

インスタンスメソッド

self

クラスメソッド

cls

スタティックメソッド

なし

オーバーライドできるか

インスタンスメソッド

可能

クラスメソッド

可能

スタティックメソッド

不可