歩いたら休め

なんでこんな模様をしているのですか?

【Python】@classmethodと@staticmethodの使いどころ

今日は @classmethod@staticmethod の使い分け方が話題になりました。私はなんとなく「コンストラクタが複数ある場合は @classmethod を使う」ようにしています。ただ、他の使い道も自分が知らないだけであるんじゃないかと思い、少し調べてみました。

複数の初期化処理を切り分ける(Factory Methodパターン)

こちらの記事にある通りです。

blog.pyq.jp

よく使われる例としては、そのクラスを作るメソッドを書くことです。 以下の例ではクラス Item と、Itemの情報をあるAPIから取得して返す retrieve_from_api というクラスメソッドを実装しています。

class Item:
    def __init__(self, id, name):
        self.id = id
        self.name = name

    @classmethod
    def retrieve_from_api(cls, id):
        res = requests.get(f"https://api.example.com/items/{id}")
        data = res.json()
        return cls(id, data["name"])

www.programiz.com

これはFactory Methodパターンと呼ばれるデザインパターンです。

pydp.info

インスタンス間で共通の変数を保持する

elicon.blog57.fc2.com

やや古い記事なので、Python2系の xrange が使われていて少し懐かしいですね。

class Shape:
    collection = set()
    def __init__(self,x, y):
        self.x = x
        self.y = y

    def update(self):
        self.x += 1
        self.y += 1

    @classmethod
    def add_new_shape(cls, (x, y)):
        shape = Shape(x, y)
        Shape.collection.add(shape)

    @classmethod
    def update_all(cls):
        for shape in Shape.collection:
            shape.update()

def main():
    for p in xrange(10):
        Shape.add_new_shape((p, p))

    q = 0
    while q < 60:
        Shape.update_all()
        q += 1

if __name__ == "__main__":
    main()

(おまけ)@staticmethodの使いどころ

elicon.blog57.fc2.com

また、 @staticmethod は「関数をまとめたクラスオブジェクト(モジュール)を作る場合」に使っています。ただ、Pythonだとファイル単位でモジュールができるので、個人的にはあまり必要性を感じたことがないです。

あとはインスタンス変数やインスタンスメソッドにアクセスしないときにも @staticmethod を使いますが、個人的な経験では、結局後で他のメソッドを呼ぶことになって self を書き足すことが多かったのであまりメリットは感じません。

atsuoishimoto.hatenablog.com

こちらの例は鮮やかですが、なかなかこういう機会はなさそう。