python 使い方 - @staticmethodと@classmethodの違いは何ですか?




呼び出し クラス (20)

@staticmethodで装飾された関数と@staticmethodで装飾された関数の違いは何ですか?


Answers

たぶん少しのコード例が役に立ちます: fooclass_foostatic_foo呼び出しシグネチャの違いにclass_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)

クラスを使用してclass_fooを呼び出すこともできます。 実際、クラスメソッドを何かを定義すると、クラスインスタンスからではなくクラスから呼び出すことになるためです。 A.foo(1)はTypeErrorを発生させますが、 A.class_foo(1)うまく動作します:

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

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

staticメソッドでは、 self (オブジェクトインスタンス)もcls (クラス)も暗黙的に第1引数として渡されません。 インスタンスやクラスから呼び出すことができる点を除いて、プレーン関数のように動作します。

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

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

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

fooは単なる関数ですが、 a.fooを呼び出すと、関数を取得するだけでなく、その関数の最初の引数としてバインドされたオブジェクトインスタンスを持つ関数の部分的に適用されたバージョンが得られます。 fooは2つの引数を、 a.fooは1つの引数しか期待していa.fooん。

afooバインドされています。 これは、以下の用語「束縛」によって意味されるものである:

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

a.class_fooでは、 aa.class_fooにバインドされず、class Aclass_fooバインドされclass_foo

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

ここで、 a.static_fooメソッドでは、たとえそれがメソッドであっても、 a.static_fooは引数がバインドされていない良い 'ole関数を返します。 static_fooは1つの引数をa.static_fooa.static_fooは1つの引数も必要とします。

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

もちろん、クラスA static_fooを呼び出すと、同じことが起こります。

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

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について説明しa_normal_instance_method 。 これは正確に「 インスタンスメソッド 」と呼ばれます 。 インスタンスメソッドが使用されている場合、これは部分関数として使用されます(ソース関数では、すべての値に対して定義された合計関数とは異なります)。使用されると、最初の引数はインスタンスのインスタンスとして事前定義されます。すべての属性を持つオブジェクトです。 オブジェクトにバインドされたインスタンスがあり、オブジェクトのインスタンスから呼び出される必要があります。 通常、インスタンスのさまざまな属性にアクセスします。

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

', '

インスタンスメソッドを使用して、この文字列を結合して別のiterableに結合すると、iterableリストの関数であることに加えて、インスタンスの関数であることは明らかです。 ['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'

静的メソッド

静的メソッドはインスタンスを引数として取りませ

モジュールレベルの機能に非常によく似ています。

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

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

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

# 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'

クラスメソッド

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

組み込みのクラスメソッドの最も標準的な例はdict.fromkeysです。 これは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'>

他の同様のコンストラクタの例については、 パンダのソースコードを参照してください。また、 classmethodstaticmethod公式のPythonドキュメントを参照してください。


クラスメソッドは、名前が示唆するように、オブジェクトではなくクラスを変更するために使用されます。クラスを変更するには、クラス属性を変更します(オブジェクト属性ではない)。これはクラスの更新方法です。これは、クラスメソッドがクラス(通常は '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."

#!/usr/bin/python
#coding:utf-8

class Demo(object):
    def __init__(self,x):
        self.x = x

    @classmethod
    def addone(self, x):
        return x+1

    @staticmethod
    def addtwo(x):
        return x+2

    def addthree(self, x):
        return x+3

def main():
    print Demo.addone(2)
    print Demo.addtwo(2)

    #print Demo.addthree(2) #Error
    demo = Demo(2)
    print demo.addthree(2)


if __name__ == '__main__':
    main()

私の貢献は、インスタンスが@staticmethod間接的に呼び出す方法を含め、 @staticmethod @classmethod@staticmethod 、およびインスタンスメソッドの違いを示しています。 インスタンスから@staticmethodを間接的に呼び出すのではなく、それを非公開にするのは、もっと「ピジョンソニック」かもしれません。 プライベートメソッドから何かを得ることは、ここでは実証されていませんが、基本的に同じ概念です。

#!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)
'''
"""

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

@staticmethod関数は、クラス内で定義された関数にすぎません。 クラスをインスタンス化せずに呼び出し可能です。 継承によって定義が不変です。

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

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

  • ファクトリメソッド 。たとえば、ある種の前処理を使用してクラスのインスタンスを作成するために使用されます。
  • 静的メソッドを呼び出す静的メソッド :いくつかの静的メソッドで静的メソッドを分割する場合は、クラス名をハードコードするのではなく、クラスメソッド

@classmethodと@staticmethodの間の類似性を最初に教えてください。

類似点:どちらもクラスインスタンスではなく、 クラス自体で呼び出すことができます。 ですから、どちらの意味でもClassのメソッドです。

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

したがって、静的メソッドは、ある意味では、クラス自体にバインドされておらず、単に関連する機能を持つ可能性があるからです。

>>> 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',)

@classmethod:そのクラスで作成されたすべてのインスタンスへの共有グローバルアクセスを作成するのに使用できます。複数のユーザーによるレコードの更新など....私は特に、シングルトンを作成するときにfulを使用することを発見しました。 )

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


Hereでこの質問の短い記事です

@staticmethod関数は、クラス内で定義された関数にすぎません。 クラスをインスタンス化せずに呼び出し可能です。 継承によって定義が不変です。

@classmethod関数もクラスをインスタンス化せずに呼び出し可能ですが、その定義は継承を介してParentクラスではなくSubクラスに従います。 @classmethod関数の最初の引数は常にcls(クラス)でなければならないからです。


静的メソッド対クラスメソッドに関するもう一つの考慮事項は、継承を伴います。 次のクラスがあるとします。

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

そして、子クラスのbar()をオーバーライドする必要があります:

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

これはうまくFoo2ますが、子クラス( Foo2 )のbar()実装では、そのクラス固有のものを利用できなくなりました。 たとえば、 Foo2bar() 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" 

この問題を回避するには、 bar() Foo2.magic()内のFoo2.magic()を呼び出すことですが、あなた自身が繰り返しています( Foo2の名前が​​変更された場合、そのbar()メソッドを更新することを忘れないでください)。

Foo決定は、派生クラスの共通コードをリファクタリングする能力に影響しているため(つまり、拡張が難しい)、 オープン/クローズドの原則を少し違反してます。 bar()classmethodあった場合、私たちはうまくいくでしょう:

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

与える: In Foo2 MAGIC


iPythonの他のメソッドと同じように高速にハックアップすると、@staticmethodパフォーマンスがわずかに向上します(ナノ秒単位)が、それ以外の場合は機能しないようです。また、staticmethod()コンパイル中にメソッドを処理する追加の作業(スクリプトを実行するときにコードが実行される前に発生する)によって、パフォーマンスの向上はおそらく無くなります。

コードの読みやすさのために@staticmethod、あなたのメソッドが、ナノ秒のカウントを行う作業の負荷に使用されない限り、私は避けることにします。


staticメソッドは、呼び出されたクラスまたはインスタンスについて何も知らないメソッドです。 渡された引数だけを取得し、暗黙的な第1引数は取得しません。 Pythonでは基本的に役に立たないのですが、静的メソッドの代わりにモジュール関数を使うことができます。

一方、クラスメソッドは、呼び出されたクラス、または呼び出されたインスタンスのクラスを最初の引数として渡すメソッドです。 これは、メソッドをクラスのファクトリにする場合に便利です。最初の引数として呼び出された実際のクラスを取得するため、サブクラスが関与している場合でも、常に適切なクラスをインスタンス化できます。 たとえば、クラスメソッドであるdict.fromkeys()がサブクラスで呼び出されたときにサブクラスのインスタンスを返す方法を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します。 @staticmethodは暗黙の引数はありません。


私はC ++、Java、そしてPythonでプログラミング言語を学び始めました。そして、この質問は、私がそれぞれの簡単な使い方を理解するまで、私にも邪魔になりました。

クラスメソッド: PythonはJavaと異なり、C ++にはコンストラクタのオーバーロードがありません。 そして、これを達成するために、 classmethod使用することができます。 以下の例でこれについて説明します

first_namelast_nameという2つの引数をとり、 Personのインスタンスを作成するPersonクラスがあるとしましょう。

class Person(object):

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

さて、あなた first_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

しかし、あなたは以下のように@classmethodを使って同じことを達成することができます

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, "")

静的メソッド:これはむしろ単純で、インスタンスやクラスにバインドされていないので、単にクラス名を使って呼び出すことができます。

上の例では、 first_nameが20文字を超えないように検証する必要があるとします。単純にこれを行うことができます。

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

クラス名を使って簡単に呼び出すことができます

Person.validate_name("Gaurang Shah")

私はより良い質問は "@classmethodと@staticmethodのどちらを使うのですか?"ということです。

@classmethodを使用すると、クラス定義に関連付けられているプラ​​イベートメンバーに簡単にアクセスできます。 これは、シングルトンや、作成されたオブジェクトのインスタンスの数を制御するファクトリクラスを実行するのに最適な方法です。

@staticmethodはパフォーマンス上の限界がありますが、クラス外のスタンドアロン関数としては達成できなかった、クラス内の静的メソッドの生産的使用をまだ見ていません。


私は例を使って基本的な違いを説明しようとします。

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 - 静的メソッドは自己メソッドを呼び出すことはできませんが、他の静的メソッドおよびクラスメソッドを呼び出すことはできます

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

4クラスメソッドはオブジェクトにバインドされず、クラスにバインドされます。


@ececatorsがPython 2.4で追加されました。あなたがPython <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)

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

_is_cluster_forメソッドをクラスメソッドにするもう1つのメリットは、サブクラスが実装の変更を決めることができるようにすることです。これはかなり汎用的で複数のタイプのクラスターを処理できるためです。


静的メソッド:

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

静的メソッドの利点:

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

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

クラスメソッド:

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

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

クラスメソッドとPythonの静的メソッド

クラスメソッド

@classmethodデコレータは、関数が定義された後に評価される式である組み込み関数デコレータです。 その評価の結果は、あなたの関数定義を陰にします。

クラスメソッドは、インスタンスメソッドがインスタンスを受け取るのと同じように、暗黙的な第1引数としてクラスを受け取ります

構文:

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

fun: function that needs to be converted into a class method
returns: a class method for function.
  • クラスメソッドはクラスにバインドされたメソッドであり、クラスのオブジェクトではありません。
  • オブジェクトインスタンスではなくクラスを指すクラスパラメータを取るので、クラスの状態にアクセスできます。
  • クラスのすべてのインスタンスに適用されるクラス状態を変更できます。 たとえば、すべてのインスタンスに適用可能なクラス変数を変更できます。

静的メソッド

静的メソッドは暗黙の第1引数を受け取りません。

構文:

class C(object):
    @staticmethod
    def fun(arg1, arg2, ...):
        ...
returns: a static method for function fun.
  • 静的メソッドは、クラスにバインドされたメソッドでもあり、クラスのオブジェクトではありません。
  • 静的メソッドはクラスの状態にアクセスしたり、クラスの状態を変更することはできません。
  • メソッドがクラス内に存在することは意味があるので、クラス内に存在します。

クラスメソッドと静的メソッド

  • クラスメソッドは第1パラメータとしてclsをとりますが、静的メソッドは特定のパラメータを必要としません。
  • クラスメソッドは、静的メソッドがアクセスまたは変更できない間に、クラス状態にアクセスまたは変更できます。
  • Pythonでは@classmethodデコレータを使用してクラスメソッドを作成し、@staticmethodデコレータを使用してPythonでスタティックメソッドを作成します。

何を使うの?

  • 私たちは、通常、ファクトリメソッドを作成するためにクラスメソッドを使用します。 ファクトリメソッドは、さまざまなユースケースに対してクラスオブジェクト(コンストラクタに似ています)を返します。
  • 私たちは一般に、静的メソッドを使用してユーティリティ関数を作成します。

どのようにクラスメソッドと静的メソッドを定義するのですか?

Pythonでクラスメソッドを定義するには、@classmethodデコレータを使用し、@staticmethodデコレータを使用する静的メソッドを定義します。

両方の違いを理解するための例を見てみましょう。 Personというクラスを作成したいとしましょう。 現在、PythonはC ++やJavaのようなメソッドのオーバーロードをサポートしていないので、クラスメソッドを使用してファクトリメソッドを作成しています。 以下の例では、classメソッドを使用して、誕生年からpersonオブジェクトを作成します。

上で説明したように、私たちは静的メソッドを使用してユーティリティ関数を作成します。 以下の例では、人が大人であるかどうかを確認するために静的メソッドを使用しています。

実装

# Python program to demonstrate 
# use of class method and static method.
from datetime import date

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    # a class method to create a Person object by birth year.
    @classmethod
    def fromBirthYear(cls, name, year):
        return cls(name, date.today().year - year)

    # a static method to check if a Person is adult or not.
    @staticmethod
    def isAdult(age):
        return age > 18

person1 = Person('mayank', 21)
person2 = Person.fromBirthYear('mayank', 1996)

print person1.age
print person2.age

# print the result
print Person.isAdult(22)

出力

21
21
True

Reference


It's returning a generator. I'm not particularly familiar with Python, but I believe it's the same kind of thing as C#'s iterator blocks if you're familiar with those.

The key idea is that the compiler/interpreter/whatever does some trickery so that as far as the caller is concerned, they can keep calling next() and it will keep returning values - as if the generator method was paused . Now obviously you can't really "pause" a method, so the compiler builds a state machine for you to remember where you currently are and what the local variables etc look like. This is much easier than writing an iterator yourself.





python oop methods python-decorators