109

While integrating a Django app I have not used before, I found two different ways to define functions inside the class. The author seems to use them both distinctively and intentionally. The first one is the one that I myself use a lot:

class Dummy(object):

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

The other one is the one I never use, mostly because I do not understand when and what to use it for:

class Dummy(object):

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

The classmethod decorator in the python documentation says:

A class method receives the class as the implicit first argument, just like an instance method receives the instance.

So I guess cls refers to Dummy itself (the class, not the instance). I do not exactly understand why this exists, because I could always do this:

type(self).do_something_with_the_class

Is this just for the sake of clarity, or did I miss the most important part: spooky and fascinating things that couldn't be done without it?

4

4 に答える 4

83

あなたの推測は正しいです - あなたは がどのよう 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()

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

  1. self.some_function()その呼び出しがたまたま出現するクラスではなくsome_function、実際のタイプののバージョンを呼び出します (クラスの名前が変更されている場合は注意する必要はありません)。self
  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) をクラス (またはオブジェクト) のメソッドに適合させることです。

于 2012-05-14T15:58:43.770 に答える
0

Pythonでの の最も一般的な用途のclassmethod1 つは、オブジェクトを構築するための最も効率的な方法の 1 つであるファクトリです。classmethods は s と同様staticmethodに、クラス インスタンスの構築を必要としないためです。(ただし、 を使用する場合はstaticmethod、関数内でインスタンス クラス名をハードコーディングする必要があります)

このブログはそれを説明する素晴らしい仕事をしています: https://iscinumpy.gitlab.io/post/factory-classmethods-in-python/

于 2022-01-23T08:38:25.470 に答える
-4

デコレーター @classmethod を追加すると、そのメソッドを Java または C++ の静的メソッドにすることになります。( static method は一般的な用語だと思います ;) ) 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 は 1 つしかなく、 TestMethod.class_method() 、 TestMethod.static_method() も 1 つしかありません。

そして重要な質問。これらのメソッドが必要な理由。

classmethod または staticmethod は、そのクラスをファクトリとして作成する場合、またはクラスを一度だけ初期化する必要がある場合に役立ちます。ファイルを一度開き、feed メソッドを使用してファイルを 1 行ずつ読み取るようにします。

于 2012-05-14T15:59:47.243 に答える