web-dev-qa-db-ja.com

いつ@classmethodを使用し、いつdef method(self)を使用する必要がありますか?

Django私が前に使用したことのないアプリを統合している間、クラスで関数を定義するために使用される2つの異なる方法を発見しました。たくさん:

class Dummy(object):

    def some_function(self,*args,**kwargs):
        do something here
        self is the class instance

もう1つは、主に私がそれをいつ使うべきか、そして何のために:

class Dummy(object):

    @classmethod
    def some_function(cls,*args,**kwargs):
        do something here
        cls refers to what?

Python docs)では、classmethodデコレータについて次の文で説明しています。

インスタンスメソッドがインスタンスを受け取るように、クラスメソッドは暗黙の最初の引数としてクラスを受け取ります。

したがって、clsDummy自体(インスタンスではなくclass)を指していると思います。私は常にこれを行うことができるので、これが存在する理由を正確に理解していません:

type(self).do_something_with_the_class

これは単に明快さのためだけですか、それとも最も重要な部分を見逃しましたか?それなしではできなかった不気味で魅力的なことですか?

69
marue

あなたの推測は正しいです-あなたは理解していますhowclassmethodsが機能します。

その理由は、これらのメソッドは、クラスでインスタンスORの両方で呼び出すことができるということです(両方の場合、クラスオブジェクトは最初の引数として渡されます):

_class Dummy(object):

    @classmethod
    def some_function(cls,*args,**kwargs):
        print cls

#both of these will have exactly the same effect
Dummy.some_function()
Dummy().some_function()
_

インスタンスでこれらを使用する場合:インスタンスでクラスメソッドを呼び出すには、少なくとも2つの主な用途があります。

  1. self.some_function()は、実際にselfの型で_some_function_のバージョンを呼び出します。呼び出しが発生するクラスではなく、クラスが注意を払う必要はありません名前が変更されます);そして
  2. 何らかのプロトコルを実装するために_some_function_が必要であるが、クラスオブジェクトのみを呼び出すと便利な場合。

staticmethodとの違いstaticmethodと呼ばれる、インスタンスデータにアクセスしないメソッドを定義する別の方法があります。これにより、暗黙の最初の引数をまったく受け取らないメソッドが作成されます。したがって、呼び出されたインスタンスまたはクラスに関する情報は渡されません。

_In [6]: class Foo(object): some_static = staticmethod(lambda x: x+1)

In [7]: Foo.some_static(1)
Out[7]: 2

In [8]: Foo().some_static(1)
Out[8]: 2

In [9]: class Bar(Foo): some_static = staticmethod(lambda x: x*2)

In [10]: Bar.some_static(1)
Out[10]: 2

In [11]: Bar().some_static(1)
Out[11]: 2
_

私が見つけた主な用途は、既存の関数(selfを受け取るとは思わない)をクラス(またはオブジェクト)のメソッドに適応させることです。

63
Marcin