Pythonのヒント、コツ、ハック(パート4、最終)

これは記事の翻訳の最後の部分です。 デコレータ、関数のスイッチ、クラスに関するいくつかの情報。



5.機能



5.4デコレータ


関数デコレータは非常にシンプルですが、これまでに見たことがない場合、どのように機能するかを理解するのは難しいでしょう。 これは、ほとんどのPython構文とは異なり、明らかではありません。 デコレータは、別の関数をラップする関数です。最初にメイン関数が作成され、次にデコレータに渡されます。 デコレータは、プログラムの残りの部分で元の関数の代わりに使用される新しい関数を返します。



私たちはもうこれにとどまりません。 構文は次のとおりです。



def decorator1(func): return lambda: func() + 1 def decorator2(func): def print_func(): print func() return print_func @decorator2 @decorator1 def function(): return 41 function() #  "42"
      
      







この例では、関数はdecorator1に渡され、関数を呼び出す関数を返し、その結果より1大きい数値を返します。 この関数はdecorator2に渡され、decorator2がそれを呼び出して結果を出力します。 そうです。



次の例はまったく同じですが、より冗長です。



 def decorator1(func): return lambda: func() + 1 def decorator2(func): def print_func(): print func() return print_func def function(): return 41 function = decorator2(decorator1(function)) function() #  "42"
      
      





通常、デコレータは関数に新しい機能を追加するために使用します(クラスメソッドの作成を参照)。 多くの場合、それらはまったく使用されません。 しかし、コードを理解するには、それが何であるかを知る必要があります。



デコレータの詳細については、著者の記事「Python Decorators Do n't Not(())Scary」博士の記事「Python Decorators」を参照してください。 Dobbsまたはドキュメント「関数定義」セクション



5.5辞書を使用していくつかの機能の1つを開始する


switchステートメントがありませんか? Pythonには、関数に同等のスイッチがないことをご存知かもしれません(複数のエリフがない限り)。 ただし、関数のディクショナリを作成することにより、その動作を再現できます。 たとえば、キーストロークを処理すると、次の機能があります。



 def key_1_pressed(): print '  1' def key_2_pressed(): print '  2' def key_3_pressed(): print '  3' def unknown_key_pressed(): print '  '
      
      





通常の方法はelifを使用しています:



 keycode = 2 if keycode == 1: key_1_pressed() elif keycode == 2: key_2_pressed() elif number == 3: key_3_pressed() else: unknown_key_pressed() #  "  2"
      
      





しかし、キーが対応するキーコードの値である辞書にすべての関数を入れることもできます。 未知のキーコードを受け取った場合でも処理できます。



 keycode = 2 functions = {1: key_1_pressed, 2: key_2_pressed, 3: key_3_pressed} functions.get(keycode, unknown_key_pressed)()
      
      





明らかに、このコードは前のコードよりもずっと明確です(特に多数の関数を使用する場合)。



6.クラス



6.1自己の手動転送


メソッドは通常の関数です。オブジェクトのインスタンスで呼び出された場合、このインスタンスは最初の引数として渡されます(通常はselfと呼ばれます)。 何らかの理由でインスタンスでメソッドを呼び出さない場合、最初の引数として常にインスタンスを手動で渡すことができます。 例:



 class Class: def a_method(self): print ', !' instance = Class() instance.a_method() #  ', !',  .    : Class.a_method(instance) #  ', !'
      
      





内側から見ると、これらの式はまったく同じです。



6.2メソッドまたはプロパティの存在の確認


オブジェクトに特定のメソッドまたはプロパティがあるかどうかを知りたいですか? オブジェクトと属性名を受け取るhasattr組み込み関数を使用できます。



 class Class: answer = 42 hasattr(Class, 'answer') #  True hasattr(Class, 'question') #  False
      
      





また、属性の存在を確認し、組み込みのgetattr関数を使用して取得することもできます。この関数は、オブジェクトと属性名も受け入れます。 3番目の引数はオプションであり、デフォルト値を設定します。 属性が見つからず、3番目の引数が指定されていない場合、AttributeError例外がスローされます。



 class Class: answer = 42 getattr(Class, 'answer') #  42 getattr(Class, 'question', '  6x9?') #  "  6x9?" getattr(Class, 'question') #   AttributeError
      
      





getattrとhasattrを頻繁に使用しないでください。 プロパティの存在を確認する必要があるようにクラスを作成した場合、すべてが間違っていました。 このプロパティは常に存在している必要があり、使用しない場合は[なし]に設定できます。 これらの関数は、主にポリモーフィズム、つまり、コード内の任意のタイプのオブジェクトを使用する機能をサポートするために使用されます。



6.3作成後のクラスの変更


このクラスのインスタンスが作成された後でも、クラスの作成後、クラスのプロパティとメソッドを追加、変更、削除できます。 これを行うには、Class.attributeエントリを使用します。 変更は、いつ作成されたかに関係なく、クラスのすべてのインスタンスに適用されます。



 class Class: def method(self): print ', ' instance = Class() instance.method() #  ", " def new_method(self): print '  !' Class.method = new_method instance.method() #  "  !"
      
      





フィクション。 しかし、既存の方法を変更することに夢中にならないでください、これは悪い形です。 さらに、これは可変クラスを使用するメソッドを混乱させる可能性があります。 一方、メソッドの追加はそれほど危険ではありません。



6.4クラスメソッドの作成


クラスを作成するときに、インスタンスではなくクラスから呼び出される関数が必要になる場合があります。 このメソッドは新しいインスタンスを作成する場合もあれば、インスタンスの個々のプロパティに依存しない場合もあります。 Pythonでこれを行うには2つの方法があり、どちらもデコレータを介して動作します。 選択は、メソッドを呼び出したクラスを知る必要があるかどうかによって異なります。



classメソッドは、最初の引数で呼び出したクラスを受け取ります(同様に、通常のメソッドは最初の引数で対応するインスタンスを受け取ります)。 このメソッドは、同じクラスから起動されるか、サブクラスから起動されるかを認識します。



静的メソッドには、開始場所に関する情報がありません。 これは通常の機能であり、範囲が異なります。



静的メソッドとクラスメソッドの両方を、クラスから直接呼び出すことができます。



 class Class: @classmethod def a_class_method(cls): print '   %s' % cls @staticmethod def a_static_method(): print '  ,  ' def an_instance_method(self): print '   %s' % self instance = Class() Class.a_class_method() instance.a_class_method() #   "   __main__.Class" Class.a_static_method() instance.a_static_method() #   "  ,  " Class.an_instance_method() #   TypeError instance.an_instance_method() #  -  "   <__main__.Class instance at 0x2e80d0>"
      
      





おわりに



もっとインスピレーションを与えるアイデアが必要ですか? 手始めに、 Python Built-in Functionsページをご覧になることをお勧めします。 あなたが聞いたことがないかもしれないかなりの良い機能があります。



役に立つトリックや知っておくべきことがあれば、著者はそれらをあなたの記事に追加することを提案します



幸せなプログラミング。



著者の他の記事や、 ここにある情報源に精通することができます



PDFの記事全文



All Articles