この記事を読むとできるようになること
- 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=このクラス自身)
スタティックメソッド
- @staticmethodデコレーター
- 引数不要
使い分け
インスタンスメソッド
ポリモーフィズムをガンガン活用して行きたい場合はインスタンスメソッド(複雑な機能要件、パターンが多く各具象クラスごとに異なる振る舞いをさせたい場合など。つまり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
スタティックメソッド
なし
オーバーライドできるか
インスタンスメソッド
可能
クラスメソッド
可能
スタティックメソッド
不可