質問

はどう違うの機能を飾った @staticmethod 一飾 @classmethod?

役に立ちましたか?

解決

おそらく少しのコード例が役立ちます:fooclass_foo、およびstatic_fooのコール署名の違いに注意してください:

class A(object):
    def foo(self, x):
        print "executing foo(%s, %s)" % (self, x)

    @classmethod
    def class_foo(cls, x):
        print "executing class_foo(%s, %s)" % (cls, x)

    @staticmethod
    def static_foo(x):
        print "executing static_foo(%s)" % x    

a = A()

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

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

classmethods を使用すると、オブジェクトインスタンスのクラスは、selfの代わりに暗黙的に最初の引数として渡されます。

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

クラスを使用してA.foo(1)を呼び出すこともできます。実際、何かを定義すると クラスメソッドの場合は、おそらくクラスインスタンスからではなくクラスから呼び出すつもりだからです。 A.class_foo(1)はTypeErrorを送出しますが、clsは問題なく動作します:

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

クラスメソッドの使用法の1つは、継承可能な代替コンストラクタを作成することです。


staticmethods では、a.foo(オブジェクトインスタンス)もa.class_foo(クラス)も最初の引数として暗黙的に渡されません。インスタンスまたはクラスから呼び出すことができる点を除いて、プレーン関数のように動作します。

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

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

静的メソッドは、クラスとクラスとの論理的な接続を持つ関数をグループ化するために使用されます。


Aは単なる関数ですが、a.static_fooを呼び出すと、関数を取得するだけでなく、 <!> quot;部分的に適用された<!> quot;関数の最初の引数としてバインドされたオブジェクトインスタンス<=>を持つ関数のバージョン。 <=>には2つの引数が必要ですが、<=>には1つの引数しか必要ありません。

<=>は<=>にバインドされます。それが<!> quot; bound <!> quotという用語の意味するところです。以下:

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

<=>を使用すると、<=>は<=>にバインドされず、クラス<=>は<=>にバインドされます。

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

ここで、staticmethodでは、メソッドであるにもかかわらず、<=>は単に戻ります 引数がバインドされていない適切な 'ole関数。 <=>引数が1つ必要です。 <=>引数も1つ必要です。

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

そしてもちろん、代わりにクラス<=>で<=>を呼び出したときにも同じことが起こります。

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

他のヒント

staticmethod は、呼び出されたクラスまたはインスタンスについて何も知らないメソッドです。渡された引数のみを取得し、暗黙の最初の引数は取得しません。 Pythonでは基本的に使い物になりません-staticmethodの代わりにモジュール関数を使用できます。

一方、

classmethod は、呼び出されたクラス、または呼び出されたインスタンスのクラスを最初の引数として渡すメソッドです。これは、メソッドをクラスのファクトリにしたい場合に便利です。メソッドが最初の引数として呼び出された実際のクラスを取得するため、サブクラスが関係している場合でも、常に適切なクラスをインスタンス化できます。たとえば、クラスメソッドであるdict.fromkeys()がサブクラスで呼び出されたときにサブクラスのインスタンスをどのように返すかに注目してください。

>>> class DictSubclass(dict):
...     def __repr__(self):
...         return "DictSubclass"
... 
>>> dict.fromkeys("abc")
{'a': None, 'c': None, 'b': None}
>>> DictSubclass.fromkeys("abc")
DictSubclass
>>> 

基本的に@classmethodは、最初の引数が(クラスインスタンスではなく)呼び出し元のクラスであるメソッドを作成します。@staticmethodには暗黙的な引数はありません。

公式のPythonドキュメント:

@classmethod

  

クラスメソッドはクラスを次のように受け取ります   暗黙の最初の引数、ちょうど   インスタンスメソッドはインスタンスを受け取ります。   クラスメソッドを宣言するには、これを使用します   イディオム:

class C:
    @classmethod
    def f(cls, arg1, arg2, ...): ... 
     

@classmethod形式は関数です    decorator <!>#8211;の説明を参照してください    Functionの関数定義   詳細については をご覧ください。

     

クラスで呼び出すことができます   (C.f()など)またはインスタンス   (C().f()など)。インスタンスは   クラスを除いて無視されます。もし   クラスメソッドが派生に対して呼び出されます   クラス、派生クラスオブジェクトは   暗黙の最初の引数として渡されます。

     

クラスメソッドはC ++とは異なります   またはJava静的メソッド。お望みならば   それらについては、 staticmethod() をご覧ください。   セクション。

@staticmethod

  

静的メソッドは、   暗黙の最初の引数。を宣言する   静的メソッド、このイディオムを使用します:

class C:
    @staticmethod
    def f(arg1, arg2, ...): ... 
     

@staticmethod形式は関数です    decorator <!>#8211;の説明を参照してください    Functionの関数定義   詳細については をご覧ください。

     

クラスで呼び出すことができます   (classmethod()など)またはインスタンス   (<=>など)。インスタンスは   クラスを除いて無視されます。

     

Pythonの静的メソッドは似ています   JavaまたはC ++で見つかったもの。のために   より高度なコンセプト、参照   このセクションの <=>

こちらはこれに関する短い記事です質問

  

@staticmethod関数は、クラス内で定義された関数にすぎません。最初にクラスをインスタンス化せずに呼び出し可能です。 It <!>#8217; sの定義は、継承を介して不変です。

     

@classmethod関数もクラスをインスタンス化せずに呼び出し可能ですが、その定義は継承を介して親クラスではなくサブクラスに従います。 That <!>#8217; s @classmethod関数の最初の引数は常にcls(クラス)でなければならないためです。

@staticmethod を使用するか、または @classmethod メソッド内を確認する必要があります。 メソッドがクラス内の他の変数/メソッドにアクセスする場合は、@ classmethodを使用します。一方、メソッドがクラスの他の部分に触れない場合は、@ staticmethodを使用します。

class Apple:

    _counter = 0

    @staticmethod
    def about_apple():
        print('Apple is good for you.')

        # note you can still access other member of the class
        # but you have to use the class instance 
        # which is not very nice, because you have repeat yourself
        # 
        # For example:
        # @staticmethod
        #    print('Number of apples have been juiced: %s' % Apple._counter)
        #
        # @classmethod
        #    print('Number of apples have been juiced: %s' % cls._counter)
        #
        #    @classmethod is especially useful when you move your function to other class,
        #       you don't have to rename the class reference 

    @classmethod
    def make_apple_juice(cls, number_of_apples):
        print('Make juice:')
        for i in range(number_of_apples):
            cls._juice_this(i)

    @classmethod
    def _juice_this(cls, apple):
        print('Juicing %d...' % apple)
        cls._counter += 1
  

Pythonの@staticmethodと@classmethodの違いは何ですか?

この擬似コードのようなPythonコードを見たことがあるかもしれません。これは、さまざまなメソッドタイプのシグネチャを示し、それぞれを説明するdocstringを提供します。

class Foo(object):

    def a_normal_instance_method(self, arg_1, kwarg_2=None):
        '''
        Return a value that is a function of the instance with its
        attributes, and other arguments such as arg_1 and kwarg2
        '''

    @staticmethod
    def a_static_method(arg_0):
        '''
        Return a value that is a function of arg_0. It does not know the 
        instance or class it is called from.
        '''

    @classmethod
    def a_class_method(cls, arg1):
        '''
        Return a value that is a function of the class and other arguments.
        respects subclassing, it is called with the class it is called from.
        '''

通常のインスタンスメソッド

最初にa_normal_instance_methodについて説明します。これは正確に<!> quot; インスタンスメソッド <!> quot;と呼ばれます。インスタンスメソッドが使用される場合、それは部分関数として使用されます(ソースコードで表示されるときにすべての値に対して定義される合計関数ではなく)。つまり、使用される場合、引数の最初は指定されたすべての属性を持つオブジェクト。オブジェクトのインスタンスがバインドされており、オブジェクトのインスタンスから呼び出す必要があります。通常、インスタンスのさまざまな属性にアクセスします。

たとえば、これは文字列のインスタンスです:

', '

この文字列でインスタンスメソッドjoinを使用して別の反復可能オブジェクトを結合する場合、 明らかに、反復可能なリストの機能であることに加えて、インスタンスの機能である['a', 'b', 'c']

>>> ', '.join(['a', 'b', 'c'])
'a, b, c'

バインドされたメソッド

インスタンスメソッドは、後で使用するためにドットルックアップを介してバインドできます。

たとえば、これはstr.joinメソッドを':'インスタンスにバインドします:

>>> join_with_colons = ':'.join 

そして、後で最初の引数が既にバインドされている関数としてこれを使用できます。このようにして、インスタンスの部分関数のように機能します。

>>> join_with_colons('abcde')
'a:b:c:d:e'
>>> join_with_colons(['FF', 'FF', 'FF', 'FF', 'FF', 'FF'])
'FF:FF:FF:FF:FF:FF'

静的メソッド

静的メソッドは、インスタンスを引数として取らない

これはモジュールレベルの関数に非常に似ています。

ただし、モジュールレベルの関数はモジュール内に存在し、使用する他の場所に特別にインポートする必要があります。

ただし、オブジェクトにアタッチされている場合、インポートおよび継承も同様にオブジェクトに追従します。

静的メソッドの例は、Python 3のstr.maketransモジュールから移動したstringです。これにより、str.translateによる消費に適した変換テーブルが作成されます。以下に示すように、文字列のインスタンスから使用するとかなり愚かに見えますが、dict.fromkeysモジュールから関数をインポートするのはかなり不格好で、classmethodのようにクラスから呼び出すことができるのは良いことです

# demonstrate same function whether called from instance or not:
>>> ', '.maketrans('ABC', 'abc')
{65: 97, 66: 98, 67: 99}
>>> str.maketrans('ABC', 'abc')
{65: 97, 66: 98, 67: 99}

Python 2では、次第に有用性の低い文字列モジュールからこの関数をインポートする必要があります。

>>> import string
>>> 'ABCDEFG'.translate(string.maketrans('ABC', 'abc'))
'abcDEFG'

クラスメソッド

クラスメソッドは、暗黙的な最初の引数を取るという点でインスタンスメソッドに似ていますが、インスタンスを取る代わりに、クラスを取ることになります。多くの場合、これらはセマンティック使用を改善するための代替コンストラクタとして使用され、継承をサポートします。

組み込みのclassmethodの最も標準的な例はstaticmethodです。 dictの代替コンストラクタとして使用されます(キーが何であるかを知っていて、それらのデフォルト値が必要な場合に適しています)。

>>> dict.fromkeys(['a', 'b', 'c'])
{'c': None, 'b': None, 'a': None}

dictをサブクラス化する場合、同じコンストラクターを使用してサブクラスのインスタンスを作成できます。

>>> class MyDict(dict): 'A dict subclass, use to demo classmethods'
>>> md = MyDict.fromkeys(['a', 'b', 'c'])
>>> md
{'a': None, 'c': None, 'b': None}
>>> type(md)
<class '__main__.MyDict'>

他の同様なものについては、 pandasソースコードをご覧ください代替コンストラクタの例、および <=> の公式Pythonドキュメントも参照してください。 <=>

プログラミング言語をC ++で、次にJavaで、次にPythonで学習し始めたので、それぞれの簡単な使用法を理解するまで、この質問もかなり悩みました。

クラスメソッド: JavaやC ++とは異なり、Pythonにはコンストラクタのオーバーロードがありません。したがって、これを実現するには、classmethodを使用できます。次の例でこれを説明します

2つの引数Personおよびfirst_nameを取り、last_nameのインスタンスを作成する@classmethodクラスがあると考えてみましょう。

class Person(object):

    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

今、単一の名前、つまりclass nameのみを使用してクラスを作成する必要がある場合、Pythonではこのようなことをできません

オブジェクト(インスタンス)を作成しようとすると、エラーが発生します。

class Person(object):

    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

    def __init__(self, first_name):
        self.first_name = first_name

ただし、後述の<=>を使用して同じことを実現できます

class Person(object):

    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

    @classmethod
    def get_person(cls, first_name):
        return cls(first_name, "")

静的メソッド:これはかなり単純で、インスタンスまたはクラスにバインドされておらず、クラス名を使用して単純に呼び出すことができます。

では、上記の例で<=>が20文字を超えてはいけないという検証が必要だとしましょう。これは簡単に行えます。

@staticmethod  
def validate_name(name):
    return len(name) <= 20

そして<=>

を使用して単に呼び出すことができます
Person.validate_name("Gaurang Shah")

@decoratorsは、Python 2.4で追加されました。Python<!> ltを使用している場合。 2.4 classmethod()およびstaticmethod()関数を使用できます。

たとえば、ファクトリーメソッド(取得する引数に応じてクラスの異なる実装のインスタンスを返す関数)を作成する場合、次のようなことができます。

class Cluster(object):

    def _is_cluster_for(cls, name):
        """
        see if this class is the cluster with this name
        this is a classmethod
        """ 
        return cls.__name__ == name
    _is_cluster_for = classmethod(_is_cluster_for)

    #static method
    def getCluster(name):
        """
        static factory method, should be in Cluster class
        returns a cluster object for the given name
        """
        for cls in Cluster.__subclasses__():
            if cls._is_cluster_for(name):
                return cls()
    getCluster = staticmethod(getCluster)

また、これがクラスメソッドと静的メソッドを使用するための良い例であることを観察してください。 静的メソッドは、クラスClusterを内部的に使用するため、明らかにクラスに属します。 classmethodはクラスに関する情報のみを必要とし、オブジェクトのインスタンスは必要ありません。

_is_cluster_forメソッドをclassmethodにすることのもう1つの利点は、サブクラスが実装を変更することを決定できることです。十分ではありません。

と思うよ"というお問合わせが多いような場合に使用@classmethod vs@staticmethod?"

@classmethodときに簡単にアクセス、個人会員に関連するクラス定義で設定します。こうsingletons、またはファクトリクラスを制御するインスタンス数、作成したオブジェが存在します。

@staticmethod無限界性能を損なっている生産用の静的メソッド内でクラスな達成として単体で機能外のクラスです。

静的メソッド:

  • 自己引数のない単純な関数。
  • クラス属性で作業します。インスタンス属性ではありません。
  • クラスとインスタンスの両方から呼び出すことができます。
  • 組み込み関数staticmethod()を使用して作成します。

静的メソッドの利点:

  • クラススコープで関数名をローカライズします
  • 関数コードを使用場所に近づけます
  • 各メソッドを特別にインポートする必要がないため、モジュールレベルの関数よりもインポートの方が便利です

    @staticmethod
    def some_static_method(*args, **kwds):
        pass
    

クラスメソッド:

  • クラス名として最初の引数を持つ関数。
  • クラスとインスタンスの両方から呼び出すことができます。
  • これらは、classmethod組み込み関数で作成されます。

     @classmethod
     def some_class_method(cls, *args, **kwds):
         pass
    

@staticmethodは、メソッド記述子としてデフォルトの機能を無効にするだけです。 classmethodは、所有クラスへの参照を最初の引数として渡すコンテナ呼び出し可能オブジェクトに関数をラップします。

>>> class C(object):
...  pass
... 
>>> def f():
...  pass
... 
>>> staticmethod(f).__get__(None, C)
<function f at 0x5c1cf0>
>>> classmethod(f).__get__(None, C)
<bound method type.f of <class '__main__.C'>>

実際には、classmethodには実行時オーバーヘッドがありますが、所有クラスにアクセスできます。または、メタクラスを使用して、そのメタクラスにクラスメソッドを配置することをお勧めします。

>>> class CMeta(type):
...  def foo(cls):
...   print cls
... 
>>> class C(object):
...  __metaclass__ = CMeta
... 
>>> C.foo()
<class '__main__.C'>

静的クラスの使用方法に関する決定的なガイドPythonの抽象メソッドはこのトピックへの良いリンクの1つであり、次のように要約します。

@staticmethod 関数は、クラス内で定義された関数にすぎません。最初にクラスをインスタンス化せずに呼び出し可能です。 It <!>#8217; sの定義は、継承を介して不変です。

  • Pythonはオブジェクトのバウンドメソッドをインスタンス化する必要はありません。
  • コードを読みやすくし、オブジェクト自体の状態に依存しません;

@classmethod 関数もクラスをインスタンス化せずに呼び出すことができますが、その定義は継承を介して親クラスではなくサブクラスに従い、サブクラスでオーバーライドできます。これは、<=>関数の最初の引数が常に cls (クラス)でなければならないためです。

  • ファクトリメソッド。たとえば、何らかの前処理を使用してクラスのインスタンスを作成するために使用されます。
  • 静的メソッドを呼び出す静的メソッド:静的メソッドをいくつかの静的メソッドに分割する場合、クラス名をハードコーディングせずにクラスメソッドを使用する必要があります

最初に@classmethodで装飾されたメソッドと@staticmethodで装飾されたメソッドの類似性を教えてください。

類似性:どちらも、クラスのインスタンスではなく、クラスで呼び出すことができます。したがって、ある意味では両方ともクラスのメソッドです。

違い:クラスメソッドは最初の引数としてクラス自体を受け取りますが、静的メソッドは受け取りません。

つまり、静的メソッドは、ある意味では、クラス自体にバインドされておらず、関連する機能がある可能性があるという理由だけでそこに留まっています。

>>> class Klaus:
        @classmethod
        def classmthd(*args):
            return args

        @staticmethod
        def staticmthd(*args):
            return args

# 1. Call classmethod without any arg
>>> Klaus.classmthd()  
(__main__.Klaus,)  # the class gets passed as the first argument

# 2. Call classmethod with 1 arg
>>> Klaus.classmthd('chumma')
(__main__.Klaus, 'chumma')

# 3. Call staticmethod without any arg
>>> Klaus.staticmthd()  
()

# 4. Call staticmethod with 1 arg
>>> Klaus.staticmthd('chumma')
('chumma',)

staticmethod vs classmethodに関するもう1つの考慮事項は、継承です。次のクラスがあるとします:

class Foo(object):
    @staticmethod
    def bar():
        return "In Foo"

そして、子クラスのbar()をオーバーライドしたい場合:

class Foo2(Foo):
    @staticmethod
    def bar():
        return "In Foo2"

これは機能しますが、子クラス(Foo2)のmagic()実装では、そのクラスに固有の機能を利用できなくなっていることに注意してください。たとえば、Foo2.magic()にはFooというメソッドがあり、classmethodIn Foo2 MAGIC実装で使用する<=>:

というメソッドがあるとします
class Foo2(Foo):
    @staticmethod
    def bar():
        return "In Foo2"
    @staticmethod
    def magic():
        return "Something useful you'd like to use in bar, but now can't" 

ここでの回避策は、<=>で<=>を呼び出すことですが、繰り返します(<=>の名前が変更された場合は、その<=>メソッドを更新する必要があります)。

私にとって、これはオープン/クローズの原則のわずかな違反です。 <=>で行われた決定は、派生クラスの一般的なコードをリファクタリングする能力に影響を及ぼします(つまり、拡張に対してあまりオープンではありません)。 <=>が<=>であれば、問題ありません:

class Foo(object):
    @classmethod
    def bar(cls):
        return "In Foo"

class Foo2(Foo):
    @classmethod
    def bar(cls):
        return "In Foo2 " + cls.magic()
    @classmethod
    def magic(cls):
        return "MAGIC"

print Foo2().bar()

提供:<=>

例を使用して基本的な違いを説明します。

class A(object):
    x = 0

    def say_hi(self):
        pass

    @staticmethod
    def say_hi_static():
        pass

    @classmethod
    def say_hi_class(cls):
        pass

    def run_self(self):
        self.x += 1
        print self.x # outputs 1
        self.say_hi()
        self.say_hi_static()
        self.say_hi_class()

    @staticmethod
    def run_static():
        print A.x  # outputs 0
        # A.say_hi() #  wrong
        A.say_hi_static()
        A.say_hi_class()

    @classmethod
    def run_class(cls):
        print cls.x # outputs 0
        # cls.say_hi() #  wrong
        cls.say_hi_static()
        cls.say_hi_class()

1-初期化せずに静的メソッドとクラスメソッドを直接呼び出すことができます

# A.run_self() #  wrong
A.run_static()
A.run_class()

2-静的メソッドはselfメソッドを呼び出すことはできませんが、他のstaticおよびclassmethodを呼び出すことはできます

3-静的メソッドはクラスに属し、オブジェクトをまったく使用しません。

4-クラスメソッドはオブジェクトではなくクラスにバインドされます。

@classmethod:複数のユーザーによるレコードの更新のように、そのクラスで作成されたすべてのインスタンスへの共有グローバルアクセスを作成するために使用できます。 特に、シングルトンを作成するときにも役立つことがわかりました。.:)

@staticメソッド:関連付けられているクラスまたはインスタンスとは関係ありませんが、読みやすくするために静的メソッドを使用できます

私の貢献は、インスタンスが間接的に@classmethodを呼び出す方法など、@staticmethod、<=>、およびインスタンスメソッドの違いを示しています。しかし、インスタンスから<=>を間接的に呼び出す代わりに、プライベートにする方が<!> quot; pythonic。<!> quot;ここではプライベートメソッドから何かを取得する方法は示していませんが、基本的には同じ概念です。

#!python3

from os import system
system('cls')
# %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %

class DemoClass(object):
    # instance methods need a class instance and
    # can access the instance through 'self'
    def instance_method_1(self):
        return 'called from inside the instance_method_1()'

    def instance_method_2(self):
        # an instance outside the class indirectly calls the static_method
        return self.static_method() + ' via instance_method_2()'

    # class methods don't need a class instance, they can't access the
    # instance (self) but they have access to the class itself via 'cls'
    @classmethod
    def class_method(cls):
        return 'called from inside the class_method()'

    # static methods don't have access to 'cls' or 'self', they work like
    # regular functions but belong to the class' namespace
    @staticmethod
    def static_method():
        return 'called from inside the static_method()'
# %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %

# works even if the class hasn't been instantiated
print(DemoClass.class_method() + '\n')
''' called from inside the class_method() '''

# works even if the class hasn't been instantiated
print(DemoClass.static_method() + '\n')
''' called from inside the static_method() '''
# %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %

# >>>>> all methods types can be called on a class instance <<<<<
# instantiate the class
democlassObj = DemoClass()

# call instance_method_1()
print(democlassObj.instance_method_1() + '\n')
''' called from inside the instance_method_1() '''

# # indirectly call static_method through instance_method_2(), there's really no use
# for this since a @staticmethod can be called whether the class has been
# instantiated or not
print(democlassObj.instance_method_2() + '\n')
''' called from inside the static_method() via instance_method_2() '''

# call class_method()
print(democlassObj.class_method() + '\n')
'''  called from inside the class_method() '''

# call static_method()
print(democlassObj.static_method())
''' called from inside the static_method() '''

"""
# whether the class is instantiated or not, this doesn't work
print(DemoClass.instance_method_1() + '\n')
'''
TypeError: TypeError: unbound method instancemethod() must be called with
DemoClass instance as first argument (got nothing instead)
'''
"""

クラスメソッドは、名前が示すように、オブジェクトではなくクラスを変更するために使用されます。クラスを変更するには、クラスを更新します(オブジェクト属性ではなく)クラス属性を変更します。 これが、クラスメソッドが最初の引数としてクラス(従来は「cls」で示される)を取る理由です。

class A(object):
    m=54

    @classmethod
    def class_method(cls):
        print "m is %d" % cls.m
一方、静的メソッドは、クラスにバインドされていない機能を実行するために使用されます。つまり、クラス変数を読み書きしません。したがって、静的メソッドは引数としてクラスを取りません。クラスがクラスの目的に直接関係しない機能を実行できるようにするために使用されます。

class X(object):
    m=54 #will not be referenced

    @staticmethod
    def static_method():
        print "Referencing/calling a variable or function outside this class. E.g. Some global variable/function."

次の違いを考慮する必要がある場合があります。

Class A:
    def foo():  # no self parameter, no decorator
        pass

and

Class B:
    @staticmethod
    def foo():  # no self parameter
        pass

これはpython2とpython3の間で変更されました:

python2:

>>> A.foo()
TypeError
>>> A().foo()
TypeError
>>> B.foo()
>>> B().foo()

python3:

>>> A.foo()
>>> A().foo()
TypeError
>>> B.foo()
>>> B().foo()

したがって、クラスから直接呼び出されるメソッドにのみ@staticmethodを使用することは、python3ではオプションになりました。クラスとインスタンスの両方からそれらを呼び出す場合、<=>デコレーターを使用する必要があります。

その他のケースは、unutbusの回答で十分にカバーされています。

さまざまな洞察を提供して@staticmethod literally を分析します。

クラスの通常のメソッドは、インスタンスを最初の引数として取る暗黙的な dynamic メソッドです。
対照的に、staticmethodはインスタンスを最初の引数として受け取らないため、 'static' と呼ばれます。

staticmethodは、クラス定義の外部のメソッドと同じ通常の関数です。
幸いなことに、適用される場所に近づくためだけにクラスにグループ化されます。または、スクロールして検索することもできます。

簡単な答え。最初の引数:

  • 通常の方法:最初の引数は現在のオブジェクトです
  • classmethod:最初の引数は現在のオブジェクトのクラスです
  • staticmethod:最初の引数が削除されました

長い回答:

通常の方法

オブジェクトのメソッドが呼び出されると、最初の引数として追加の引数selfが自動的に与えられます。つまり、メソッド

def f(self, x, y)

2つの引数で呼び出す必要があります。 classmethodは自動的に渡され、オブジェクト自体です。

クラスメソッド

メソッドが装飾されている場合

@classmethod
def f(cls, x, y)

自動的に提供される引数 staticmethodではなく、のクラス Math

静的メソッド

メソッドが装飾されている場合

@staticmethod
def f(x, y)

メソッドは自動的に引数を与えられません 。呼び出されるパラメーターのみが与えられます。

使用法

  • <=>は、主に代替コンストラクタに使用されます。
  • <=>は、オブジェクトの状態を使用しません。クラスの外部の関数である可能性があります。同様の機能(Javaの<=>クラスの静的メソッドなど)を持つグループ化関数のクラス内にのみ配置します
class Point
    def __init__(self, x, y):
        self.x = x
        self.y = y

    @classmethod
    def frompolar(cls, radius, angle):
        """The `cls` argument is the `Point` class itself"""
        return cls(radius * cos(angle), radius * sin(angle))

    @staticmethod
    def angle(x, y):
        return atan(y, x)


p1 = Point(3, 2)
p2 = Point.frompolar(3, pi/4)

angle = Point.angle(3, 2)

iPythonのその他の点で同一のメソッドをすばやくハックすると、@staticmethodがわずかなパフォーマンスの向上(ナノ秒単位)をもたらすことがわかりますが、それ以外の場合は機能しません。また、パフォーマンスの向上はおそらく、コンパイル中にstaticmethod()を介してメソッドを処理する追加の作業によって消去されます(スクリプトの実行時にコードが実行される前に発生します)。

コードを読みやすくするために、ナノ秒がカウントされる大量の作業にメソッドが使用されない限り、<=>は避けたいと思います。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top