1. ホーム
  2. python

[解決済み] staticmethodとclassmethodの違いについて

2022-03-15 09:04:49

質問

で装飾された関数の違いは何ですか? @staticmethod で装飾されたものと @classmethod ?

解決方法は?

ちょっとだけ、サンプルコードが役に立つかもしれません。の呼び出しシグネチャの違いに注目してください。 foo , class_foostatic_foo :

class A(object):
    def foo(self, x):
        print(f"executing foo({self}, {x})")

    @classmethod
    def class_foo(cls, x):
        print(f"executing class_foo({cls}, {x})")

    @staticmethod
    def static_foo(x):
        print(f"executing static_foo({x})")

a = A()

以下は、オブジェクトのインスタンスがメソッドを呼び出す通常の方法です。オブジェクトのインスタンスが a が第一引数として暗黙のうちに渡される。

a.foo(1)
# executing foo(<__main__.A object at 0xb7dbef0c>, 1)


クラスメソッドで の代わりに、オブジェクトのインスタンスのクラスが暗黙のうちに第一引数として渡されます。 self .

a.class_foo(1)
# executing class_foo(<class '__main__.A'>, 1)

を呼び出すこともできます。 class_foo を使用しています。実際、何かを定義する場合 クラスメソッドを使用するのは、おそらくクラスのインスタンスからではなく クラスから呼び出すことを意図しているからでしょう。 A.foo(1) はTypeErrorを発生させますが A.class_foo(1) は正常に動作します。

A.class_foo(1)
# executing class_foo(<class '__main__.A'>, 1)

クラスメソッドの使い方の1つに 継承可能な代替コンストラクタ .


staticmethodsを使用した場合 を使用すると、どちらも self (オブジェクトのインスタンス) と cls (クラス)は暗黙のうちに第一引数として渡されます。インスタンスやクラスから呼び出すことができることを除けば、これらは普通の関数と同じようにふるまうことができます。

a.static_foo(1)
# executing static_foo(1)

A.static_foo('hi')
# executing static_foo(hi)

Staticmethods は、クラスと何らかの論理的な関係を持つ関数を、クラスにまとめるために使用されます。


foo は単なる関数ですが a.foo は、単に関数を取得するだけではありません。 オブジェクトのインスタンスと一緒に関数の "部分適用バージョンも取得します。 a を関数の第一引数としてバインドします。 foo は2つの引数を期待しますが a.foo は1つの引数だけを想定しています。

a にバインドされています。 foo . これが、以下のquot;bound"という用語の意味するところです。

print(a.foo)
# <bound method A.foo of <__main__.A object at 0xb7d52f0c>>

a.class_foo , a にはバインドされません。 class_foo ではなく、クラス A にバインドされています。 class_foo .

print(a.class_foo)
# <bound method type.class_foo of <class '__main__.A'>>

ここでは、メソッドであるにもかかわらずstaticmethodで。 a.static_foo を返すだけです。 は、引数が束縛されていない、良い'オール'関数です。 static_foo は1つの引数を期待し a.static_foo も1つの引数を期待します。

print(a.static_foo)
# <function static_foo at 0xb7d479cc>

そしてもちろん、同じように static_foo というクラスで A の代わりに

print(A.static_foo)
# <function static_foo at 0xb7d479cc>