50

これまで使用していなかったDjangoアプリケーションを統合する中で、私はクラスで関数を定義するために2つの方法を見つけました。著者は両方を非常に意図的に使用するようです。@classmethodはいつ使うべきですか?defメソッド(self)を使うべきですか?

class Dummy(object): 

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

もう一つは、私はそれを使用する際に理解し、そして何のためにしていない主な理由は、私が使用していないものです::

class Dummy(object): 

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

最初のものは、私は自分自身をたくさん使うものですPythonのドキュメントにclassmethodデコレータは、この文章で説明されている:

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

だから私はclsDummy自体(class、ないインスタンス)を参照すると思います。これが存在する理由私はいつもこれを行うことができますので、私は正確に理解していない:

type(self).do_something_with_the_class 

はちょうど明確化のために、このか、それとも私が最も重要な部分逃さなかった:することができませんでした不気味なと魅力的なものをそれなしで済ませた?

答えて

47

あなたの推測は正しいです - あなたは理解していますどのようにclassmethodの仕事。

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() 

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

ザインスタンス上でこれら:

  1. self.some_function()selfの実際のタイプにsome_functionのバージョンを呼び出します、というよりもCLAS:インスタンス上のクラスメソッドを呼び出すための少なくとも二つの主な用途があります。その呼び出しが出現するようになります(クラスの名前が変更されても注意は必要ありません)。
  2. some_functionが何らかのプロトコルを実装する必要があるが、クラスオブジェクトだけを呼び出すのに便利な場合。

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

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を受け取ることを期待していません)、既存の機能を適応させることであるために私が見つけた主な用途。

+1

いいですね。私は答えが分かりにくいのが好きなのです。 @classmethodはインスタンスを必要とせずに関数にアクセスできるようになりました。これはまさに私が探していたものです、ありがとう。 – marue

+0

@marueよろしくお願いします! – Marcin

+0

私は、インスタンス上でクラスメソッドを呼び出すのは、コーディングスタイルが悪いと言っています。そうする理由はなく、混乱の原因に過ぎません。しかし、はい(javaは同じことを許可しますが、インスタンスを通じて静的メソッドを呼び出すときにコンパイル警告を発行します) – Voo

0

デコレータ@classmethodを追加すると、そのメソッドをjavaまたはC++の静的メソッドとして作成することになります。(静的メソッドは一般用語だと思います。;) Pythonには@staticmethodもあります。 classmethodとstaticmethodの違いは、引数またはクラス名自体を使用して、クラスまたは静的変数へのアクセスを できるかどうかです。

class TestMethod(object): 
    cls_var = 1 
    @classmethod 
    def class_method(cls): 
     cls.cls_var += 1 
     print cls.cls_var 

    @staticmethod 
    def static_method(): 
     TestMethod.cls_var += 1 
     print TestMethod.cls_var 
#call each method from class itself. 
TestMethod.class_method() 
TestMethod.static_method() 

#construct instances 
testMethodInst1 = TestMethod()  
testMethodInst2 = TestMethod() 

#call each method from instances 
testMethodInst1.class_method() 
testMethodInst2.static_method() 

これらのクラスはすべてcls.cls_varを1増加させて出力します。

そして、これらのクラスで構築された同じスコープまたはインスタンスで同じ名前を使用するすべてのクラスは、それらのメソッドを共有します。 一つだけTestMethod.cls_var ありますし、また、一つだけTestMethod.class_method()、TestMethod.static_method()

そして、重要な問題があります。なぜこれらの方法が必要であろうか。

classmethodまたはstaticmethodは、そのクラスをファクトリとして にする場合、またはクラスを1回だけ初期化する必要がある場合に便利です。開いているファイルを一度作成し、フィードメソッドを使って行ごとにファイルを読み込みます。

+1

に変更された場合、大きなユースケース'は注意を必要としません。(a)静的メソッドは別のものです。 (b)クラスメソッドはすべてのクラスで共有されません。 – Marcin

+0

@Marcinは私に不明な定義とそのすべてを教えてくれてありがとう。 –

関連する問題