Python-装飾器を習う前に、いくつか理解しなければならないことがあります.

4389 ワード

そうでなければ、プログラミング言語に分からないところがあって、ちょうどこの機能を使っている人がいたら、銃を撃って彼を殺すのは、新しい特性を学ぶよりも簡単です.それから間もなく、生きているプログラマーは0.9.6バージョンのPythonを使い始めます.そして、このバージョンの理解しやすい部分を使うだけでいいです(まばたき). - Tim Peters
まず、友达と一绪に作った壁紙のダウンロードをお勧めします.各サイトの壁紙を登って、いつも好きなタイプがあります.http://wp.d2collection.com/
周知のように、Pythonの装飾器は重要で牛Xの機能であり、元の関数の機能と構造を変えずに新しい機能を追加することができます.
しかし、装飾器を理解するには多くの知識点があります.
  • 導入時、運転時
  • 閉パケットと変数の役割ドメイン
  • nonlocal

  • 一般的に私たちの装飾器は別の書類に書かれています.xxxのようです.deco.
    別のファイルに導入され、独自の関数で定義されると、アクセサリーはすぐに実行されます.(もちろんコードが書かれた直後に++が実行されたわけではありません)
    『流暢なPython』の例で
    registry = []
    
    
    def register(func):
        print('running register(%s)' % func)
        registry.append(func)
        return func
    
    
    @register
    def f1():
        print('running f1()')
    
    
    @register
    def f2():
        print('running f2()')
    
    
    def f3():
        print('running f3()')
    
    
    def main():
        print('running main()')
        print('registry ->', registry)
        f1()
        f2()
        f3()
    
    if __name__ == '__main__':
        main()
    
    

    実行結果は次のとおりです.
    running register()
    running register()
    running main()
    registry -> [, ]
    running f1()
    running f2()
    running f3()
    

    結果から先ほどの話は、装飾後、すでに運行されていることが確認できました.
    次に変数の問題について議論します.周知のように、1つの関数内部の変数は、関数の実行が終了すると破棄されます.では、小さな例を見てみましょう
    def make_averager():
        series = []
    
        def averager(new_value):
            series.append(new_value)
            total = sum(series)
            return total / len(series)
    
        return averager
    

    これは閉パケットで実現した平均数を求める方法であり,インポート実行結果は以下の通りである.
    In[2]: from average import make_averager
    In[3]: avg = make_averager()
    In[4]: avg(10)
    Out[4]: 10.0
    In[5]: avg(11)
    Out[5]: 10.5
    In[6]: avg(12)
    Out[6]: 11.0
    

    ここでよく考えている盆友は見て、毎回値が記録されていて、私はその時ここを見たとき、これは穴のお父さんではないかと思っていました.ローカル変数の実行が完了すると破棄されると誰が言ったのか(′▽`)¯(
    「クローズド・パッケージ(Closure)」は、文法クローズド・パッケージ(Lexical Closure)の略称で、自由変数を引用した関数です.この参照される自由変数はこの関数とともに存在し,それを創造する環境を離れても例外ではない.
    閉パケットは変数の役割ドメインを延長し,自由変数という名前を付けた.上のseriesは自由変数です自由変数とは、ローカルの役割ドメインでバインドされた変数を指すので、このseriesは解放されず、ずっと使用できます.
    では、この時に見てみましょう.もし私が統計したいなら、何個の数字がありますか.コードは以下のように追加されます.
    def make_averager():
        series = []
        count = 0
    
        def averager(new_value):
            count += 1
            series.append(new_value)
            total = sum(series)
            return total / len(series)
    
        return averager
    

    次のように動作します.
    In[2]: from average import make_averager
    In[3]: avg = make_averager()
    In[4]: avg(10)
    Traceback (most recent call last):
      File "/Users/WangLu/.pyenv/versions/3.5.2/lib/python3.5/site-packages/IPython/core/interactiveshell.py", line 2862, in run_code
        exec(code_obj, self.user_global_ns, self.user_ns)
      File "", line 1, in 
        avg(10)
      File "/Users/WangLu/Study/FluentPython/average.py", line 6, in averager
        count += 1
    UnboundLocalError: local variable 'count' referenced before assignment
    

    エラーが発生しました.変数を定義する前に変数が適用されました.これはさっき言ったことと一致しない.
    Pythonでは、数字やタプルなどの可変タイプは読み取り専用で、値を再付与するには変数を再作成しなければなりませんが、先ほどの例では、変数を再作成すれば自由変数ではなく、自由変数のない閉パッケージですか、閉パッケージですか.したがってPython 3にnonlocal宣言が導入され,nonlocal宣言された変数が自由変数となり,閉パケット中のデータが更新される.
    コードは次のように書き換えられます.
    def make_averager():
        series = []
        count = 0
    
        def averager(new_value):
            nonlocal count
            count += 1
            series.append(new_value)
            total = sum(series)
            return total / len(series)
    
        return averager
    

    Python 2であれば、listなどの変数を可変に設定する必要があります
    これで装飾器を実現し,呼び出すたびにハハ+メソッド名+結果を出力することができる.
    def haha_deco(func):
        def haha(*args):
            result = func(*args)
            print('   -> {},   :{}'.format(func.__name__, result))
            return result
    
        return haha
    

    呼び出し結果:
    In[2]: from haha_deco import haha_deco
    In[3]: @haha_deco
      ...: def demo(n):
      ...:     return 1 if n < 2 else n * demo(n-1)
      ...: 
    In[4]: demo(5)
       -> demo,   :1
       -> demo,   :2
       -> demo,   :6
       -> demo,   :24
       -> demo,   :120
    Out[4]: 120
    

    アクセサリーを理解したいのですが、このいくつかの点はできると思います.
    最後に
    生活を愛し、麗ちゃんを愛する