2016-11-27 10 views
4

私はPythonで静的メソッドがどのように機能するかを理解するために、この短いテスト/サンプルコードを開発しました。Pythonで@staticmethodのポイントは何ですか?

class TestClass: 
    def __init__(self, size): 
     self.size = size 

    def instance(self): 
     print("regular instance method - with 'self'") 

    @staticmethod 
    def static(): 
     print("static instance method - with @staticmethod") 

    def static_class(): 
     print("static class method") 


a = TestClass(1000) 

a.instance() 
a.static() 
TestClass.static_class() 

このコードは正しく動作し、エラーは返されません。私の質問は次のとおりです:

  1. "このメソッドはインスタンスから呼び出される"のように理解できると私は正しく理解していますか?

  2. また、@staticmethodの背後にあるロジックは何ですか?インスタンスから呼び出すことのできる静的メソッドを作成するのはどうですか?それは正確にではないどのような静的メソッドについてですか?

  3. 第3のアプローチよりも第2のアプローチが好ましい理由は何ですか? (私はデコレータが存在するので、これにポイントがあると仮定します).3番目のオプションは、よりシンプルで簡単です。

+1

これは2.xでは全く機能しません。また、 'a.static_class()'はどちらでも動作しません。 – jonrsharpe

+1

テストケースに '' TestClass.static() ''と '' a.static_class() ''を追加し、何が起こるかを観察します。これは '' @ staticmethod''がなぜ有用なのかを説明するのに役立ちます。 –

+0

* "静的メソッドの正確なものではないのですか?" * - インスタンス上で呼び出せるという利点は、 'cls.whatever()'と 'self.whatever()'が正しく動作することです。クラスとインスタンスのメソッドからクラス名を保持し、継承を正しく処理することができます。 – jonrsharpe

答えて

3

投稿はstatic methodsです。要約:

  • インスタンスメソッドは:最初の引数としてクラスを必要と
  • 静的メソッドを::
  • クラスメソッド最初の引数としてインスタンスを必要とし、最初の引数としてどちらも必要としません

質問について:

  1. はい。変数名selfは規約ですが、インスタンスに関係します。
  2. 静的メソッドを使用して、同じクラスの類似のユーティリティメソッドをグループ化することができます。
  3. クラス内のメソッドの場合は、最初の引数としてselfを追加するか、@staticmethodでメソッドを修飾する必要があります。引数なしの "装飾されていないメソッド"はエラーを発生させます。

引数を指定して呼び出された場合のこれらの動作をより明確にすることができます。あなたは、インスタンスまたはインスタンスのコンポーネント(たとえば、インスタンス属性)にアクセスする必要がある場合は、

  • :変形例:

    class TestClass: 
    
        weight = 200        # class attr 
    
        def __init__(self, size): 
         self.size = size      # instance attr 
    
        def instance_mthd(self, val): 
         print("Instance method, with 'self':", self.size*val) 
    
        @classmethod 
        def class_mthd(cls, val): 
         print("Class method, with `cls`:", cls.weight*val) 
    
        @staticmethod 
        def static_mthd(val): 
         print("Static method, with neither args:", val) 
    
    a = TestClass(1000) 
    
    a.instance_mthd(2) 
    # Instance method, with 'self': 2000 
    
    TestClass.class_mthd(2) 
    # Class method, with `cls`: 400 
    
    a.static_mthd(2) 
    # Static method, with neither args: 2 
    

    全体的に、あなたはアクセスの面でそれぞれの方法を考えることができますインスタンスメソッドを使用して、最初の引数としてselfを渡します。

  • 同様に、クラスにアクセスする必要がある場合は、クラスメソッドを使用します。
  • インスタンスまたはクラスへのアクセスが重要でない場合は、静的メソッドを使用できます。例で

通知は、上記と同じ引数が、各メソッドタイプに渡されるが、インスタンスおよびクラス属性へのアクセスは、それぞれselfclsを介して異なります。

... 

    def instance_mthd2(self, val): 
     print("Instance method, with class access via `self`:", self.__class__.weight*val) 
    ... 

a.instance_mthd2(2) 
# Instance method, with class access via `self`: 400 

REF::私はお勧めレイモンドヘッティンガーのtalkPythonのクラスの開発を見て

注意、それによって、クラスメソッドの必要性をなくす、self.__class__を使用して、インスタンスメソッドからクラスのコンポーネントにアクセスする方法がありますToolkitは、それぞれのメソッドタイプの目的を明確に説明しています。ここで

+0

Isあなたのクラスメソッドとして定義した私の例のstatic_class()? – rbrtk

+1

'@ classmethod'で装飾し、最初のargとして' cls'を渡します。それからクラスメソッドになります。 – pylang

1

は、あなたの質問への回答です:

質問1:私は「自己」は「このメソッドはインスタンスから呼び出されるようなものとして理解することができることを正しく

を理解しています"?

いいえこれは完全にTrueではありません。 selfは、関数の最初の引数がclassのインスタンスであることを意味します。例えば:

def my_class_function(self) 

は、と呼ばれることができる:

self.my_class_function() 
OR, 
my_class_function(self) 

はまた、クラスのオブジェクトへの参照としてselfを使用するneccesarryありません。何かを(有効な変数である限り)使用することができますが、selfを使用することはどこにでも従う標準です。

質問2:

その後、再び、@staticmethodの背後にあるロジックは何が - それは、インスタンスから呼び出すことができる静的メソッドを作成するのですか?静的メソッドが何であるか正確にそれではありませんか?

@staticmethod変数は、プロパティまたは関数、すなわちあなたがクラスのいずれかにアクセスするためのselfのいずれかの使用をしないでください関数内でオブジェクトのクラスへの参照を必要としない関数で使用されます。

質問3:

なぜ第二のアプローチは、第三の1つの上に有利であろうか? (私はデコレータが存在するので、これにポイントがあると仮定します).3番目のオプションは、よりシンプルで簡単です。即ち@staticmetodを用いて第2のアプローチを使用して

関数の範囲はクラス内であるように、あなたは(デコレータを使用せずに)あなたの第三のアプローチとは異なり、クラスのオブジェクトを使用して、クラス外部から自分の機能を呼び出すことができます。

1

メソッドは、呼び出されたインスタンスに対して動作します。このインスタンスは、通常はselfと呼ばれる最初のパラメータとして渡されます。

クラスメソッドは類似していますが、インスタンスの1つではなくクラスオブジェクト全体に作用します。それらは、コンストラクタやファクトリ関数として、または個々のインスタンスではなくクラスまたはすべてのインスタンスに一度に影響を与える設定の設定やその他の状況に便利です。

第3のオプションの静的メソッドは、奇妙な人です。インスタンスまたはクラスのいずれも渡しません。それらは、組織の目的のためにプログラムのクラス構造内でユーティリティ関数を入れ子にするのに適していますが、インスタンスやクラスに意図的に依存していないことを明確に(コードレビューア、リンチング、プログラムチェックツールなどに)値。そうすれば、使用していないことについての "変数は宣言されていますが使用されていない"という警告は表示されませんself

呼び出し元の観点からは、静的メソッドは他のメソッド呼び出しと同じように見えます。 @staticmethodが利用できない場合は、通常のインスタンスまたはクラスメソッドを使用することができます(ただし、「変数が使用されていません!!」というリンター警告が表示されます)。したがって、クラスメソッドとは異なり、静的メソッドはPythonの完全にオプションの部分です。言語に機能を追加するものではありません。代わりに、開発者の意図をより明確にする方法を提供します。

関連する問題