0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Pythonのclassmethodとstaticmethodの違いについて

Last updated at Posted at 2022-10-09

Pythonにはclassmethodとstaticmethodという似たような二種類のメソッドがあるが、どっちを使うべきなのか?と思ったので調べた

メソッドの書き方

classmethodの場合

@classmethod
def increment_classmethod(cls, value):
    return value + 1

staticmethodの場合

@staticmethod
def increment_staticmethod(value):
    return value + 1

違いはclassmethodの場合は第一引数がclsになるのに対して、staticmethodは純粋に引数から始まります
なのでclassmethodでcls.hogeでクラスのプロパティやメソッドにアクセスできます、ただA.hogeやるのと大差ないかなと思います

メソッドの呼び方

class A:
    
    @staticmethod
    def increment(value):
        return value + 1
    
    @classmethod
    def increment_classmethod(cls, value):
        return cls.increment(value)
    
    @staticmethod
    def increment_staticmethod(value):
        return A.increment(value)

このようなクラスがある場合、外から呼ぶ場合はどちらも呼び方は同じです

A.increment_classmethod(value)
A.increment_staticmethod(value)

ただし、同じクラス内で呼ぶ場合は、classmethodの場合第一引数がclsなので

cls.increment(value)

と呼ぶことができます

また、継承した場合はちょっと変わってきます
以下のように継承したクラスの場合

class B:
    @staticmethod
    def increment(value):
        return value + 1
    
    @classmethod
    def increment_classmethod(cls, value):
        return cls.increment(value)
    
    @staticmethod
    def increment_staticmethod(value):
        return B.increment(value)

class A(B):
    @staticmethod
    def increment(value):
        return value + 2

value = A.increment_classmethod(1)
print('classmethod:' + str(value))

value = A.increment_staticmethod(1)
print('staticmethod:' + str(value))

結果

classmethod:3
staticmethod:2

classmethodから呼ぶ場合は、cls.incrementで呼ぶことによりサブクラスのincrementが呼ばれますが
staticmethodから呼ぶ場合は、クラス名を指定する必要があるので、オーバーライドしてようがそのクラスのincrementが呼ばれます

速度

classmethodは第一引数にclsを入れる処理の分staticmethodよりも遅いらしいので計測してみました

import time

class A:
    @staticmethod
    def increment(value):
        return value + 2
    
    @classmethod
    def increment_classmethod(cls, value):
        return cls.increment(value)
    
    @staticmethod
    def increment_staticmethod(value):
        return A.increment(value)

start_time = time.time()
value = 1
for i in range(0, 1000000):
    value = A.increment_classmethod(value)
end_time = time.time()
print('classmethod:' + str(end_time - start_time) + '')

start_time = time.time()
value = 1
for i in range(0, 1000000):
    # value = A.increment_classmethod(value)
    value = A.increment_staticmethod(value)
end_time = time.time()
print('staticmethod:' + str(end_time - start_time) + '')

こんな感じで10回計測してみます
paizaで計測しました

結果

classmethod平均:0.2170754433秒
staticmethod平均:0.2145765066秒

確かにstaticmethodの方が少し早いですが、気にするレベルじゃないと思います

結論

  • クラス名書くより、cls.で書いた方が楽
  • 継承した際にオーバーライドできる
  • 速度的には気にするほどではない

という点から基本classmethod使ってれば問題ないかなと思いました

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?