Pythonの@staticmethodと@classmethodの違いって何? [Python]

このエントリーをはてなブックマークに追加

質問:

@staticmethodが付いてる関数と、@classmethodが付いてる関数の違いって何?

By Daryl Spitzer | 質問日時: Sep 25 ‘08 at 21:01



回答1:

たぶんコード例で見たほうがいいと思う:fooclass_foostatic_fooのコールのsignature(訳注:メソッド名、パラメータ、戻り値の型をあわせたもの)の違いに注意:

class A(object):
def foo(self,x):
print "を実行する foo(%s,%s)"%(self,x)
@classmethod
def class_foo(cls,x):
print "を実行する class_foo(%s,%s)"%(cls,x)
@staticmethod
def static_foo(x):
print "を実行する static_foo(%s)"%x
a=A()

以下は、オブジェクトインスタンスがメソッドを呼び出す一般的な方法。オブジェクトインスタンスaは最初の引数として暗黙的に渡される。

a.foo(1)
# foo(<__main__.A object at 0xb7dbef0c>,1)を実行する

classmethodsでは、オブジェクトインスタンスのクラスは、selfじゃなく最初の引数として暗黙的に渡される。

a.class_foo(1)
# class_foo(<class '__main__.A'>,1)を実行する

クラスを使って class_fooを呼び出すこともできるよ。実際、何かをクラスメソッドとが定義した場合、たぶんそれはクラスインスタンスからじゃなくクラスから呼び出されると仮定して定義しているはずなので。A.foo(1)はTypeErrorだけど、 A.class_foo(1)はうまくいくよ:

A.class_foo(1)
# class_foo(<class '__main__.A'>,1)を実行する

クラスメソッドとしてよく使われるのは、継承可能な代替コンストラクタを作ること。


staticmethodsでは、 self(オブジェクトインスタンス)もcls(クラス)も暗黙のうちに第1引数として渡されない。インスタンスやクラスから呼び出すことができる点を除いて、通常の関数のように動作するよ。

a.static_foo(1)
# static_foo(1)を実行する
A.static_foo('hi')
# static_foo(hi)を実行する

staticmethodsはあるクラスとそのクラスへの論理接続を持つ関数をグループ化するために使用される。


fooは単なる関数だけど、a.fooを呼び出すと、関数自身は得ることができなくて、最初の引数としてバインドされたオブジェクトインスタンス aへ”部分的に適用された”関数が与えられる。fooは2つの引数があることを期待してるけど、a.fooは1つの引数しか期待していない。

ここでafooにバインドされてる。これは、以下のように「束縛」(bound)が意味してるものでもある:

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

a.class_fooでは、aclass_fooに束縛されず、むしろクラスAclass_fooに束縛されてる。

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

staticメソッドでは、例えそれがメソッドであっても a.static_fooは何も引数がバインドされていない「古き良き」関数を返してくれる。static_fooは1つ引数があるのをを期待してて、a.static_fooも1つの引数があるのを期待してる。

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

そしてもちろん、代わりにクラスAstatic_fooを呼び出すと同じことが起こる。

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

By unutbu | 回答日時: Nov 3 ‘09 at 19:13



Source: What is the difference between @staticmethod and @classmethod in Python?

共有 コメント