
Python_デコレーター_staticmethodとclassmethodの違い #232日目
デコレーターとは、関数を引数にとって新たな関数を返す動きを使って、関数を装飾(デコレート)できる機能です。ある特定の処理を複数の関数で実行したい場合、各関数に同じ処理を記述するより、デコレーターとしてまとめていた方がコードが簡単になります。
以前、基本的な用法についてまとめてみました。
本日は、組み込みデコレーターの中でも機能が似ている「@staticmethod」と「@classmethod」の違いを整理しておきます。
@staticmethodと@classmethodの共通点
クラス内に定義されているメソッドを、クラスをインスタンス化することなく呼び出せるようになります。
例えば以下のようなケースです。
class Lion():
@staticmethod
def scratch(name):
print(name + "がひっかいた!")
[実行]
>>> Lion.scratch("タマ")
タマがひっかいた!
@staticmethodや@classmethodを使わない場合は、以下のように一度インスタンス化しないとメソッドを呼び出せません。
class Lion:
def scratch(self, name):
print(name + "がひっかいた!")
[実行]
>>> lion = Lion()
>>> lion.scratch("タマ")
タマがひっかいた!
@staticmethodと@classmethodの相違点
この2つの違いが出てくるのは、元のクラスを継承して新しいクラスを作った時です。@staticmethodは元のクラスと全く同じように動作し、@classmethodは変数を用いて継承先で動作を調整できます。
変えたくない時は@staticmethod、変えたい時は@classmethodという感じですね。
実際にコードで確認してみます。
親クラスWorkspaceを、何も変更しないクラスと、変数を上書きするクラスで継承しています。
class Workspace():
work = 'Document making'
def report(self):
print(self.work + "が完了しました")
@classmethod
def consult(cls):
print("【classmethod】" + cls.work + "について相談があります")
@staticmethod
def propose():
print("【staticmethod】" + Workspace.work + "をやるべきだと思います")
class WorkspaceAsItIs(Workspace):
pass
class OriginalWorkspace(Workspace):
work = "Appointment"
まず、Workspaceクラスをそのまま使ってみます。当然ですが、workの中身はどれも「Document making」です。
[実行]
>>> work = Workspace()
>>> work.report()
Document makingが完了しました
>>> Workspace.consult()
【classmethod】Document makingについて相談があります
>>> Workspace.propose()
【staticmethod】Document makingをやるべきだと思います
次に、ただ単にWorkspaceクラスを継承しただけのWorkAsItIsクラスを使ってみます。ここでは上記と同じ結果になります。
[実行]
>>> work = WorkspaceAsItIs()
>>> work.report()
Document makingが完了しました
>>> WorkspaceAsItIs.consult()
【classmethod】Document makingについて相談があります
>>> WorkspaceAsItIs.propose()
【staticmethod】Document makingをやるべきだと思います
最後にworkを上書きしたOriginalWorkspaceクラスです。このケースにおいて、@staticmethodと@classmethodの動作が異なります。
[実行]
>>> work = OriginalWorkspace()
>>> work.report()
Appointmentが完了しました
>>> OriginalWorkspace.consult()
【classmethod】Appointmentについて相談があります
>>> OriginalWorkspace.propose()
【staticmethod】Document makingをやるべきだと思います
@staticmethodの場合のみ、親クラスと同じDocument makingで動作しています。
用途に応じて使い分けると便利ですね。
ここまでお読みいただきありがとうございました!!