pythonアクセサリーを深く理解する

3292 ワード

1、飾りは何ですか.
装飾器は、その名の通り、「装飾」に使われています.
このように成長しています.
@xxx
その中の「xxx」はあなたの装飾器の名前です.
飾ることができるものは、関数、クラスです.
2、どうしてアクセサリーが必要なの?
装飾器は主に「サボる」ために使われる
例:
簡単な関数をたくさん書いていますが、実行中にどの関数が実行されているのか知りたいです.そして、テストを書く必要はありません.ただ、実行が終わる前に「Start」と印刷したいだけです.どうすればいいですか.このようにすることができます.
def func_name(arg):

    print 'Start func_name'
    sentences

このようにするのは間違いありません.but、あなたは考えたことがありますか.まさかあなたは本当にすべての関数の後ろにそんな一言を加えたいと思っていますか.もう一度実行して問題がないことを確認したら、printを削除してください.面倒ではありませんか.何?1つ書くのは面倒ではないと思いますが、追加する関数は10個ありますか?20個?30個?(あなたの忍耐のしきい値を超えた回数を自分で加えてください)......
もしあなたが装飾器を知っていたら、状況はだんだんよくなってきました.このように書くことができることを知っています.
def log(func):
    def wrapper(*arg, **kw):
        print 'Start %s' % func
        return func(*arg, **kw)
    return wrapper

  
@log
def func_a(arg):
    pass

@log
def func_b(arg):
    pass

@log
def func_c(arg):
    pass

ここで、log関数は装飾器です.
デコレーションを書いたら、デコレーションが必要な関数の前に@logを付けるだけでいいです.この例では,一度に3つの関数にprint文を加えた.
デザイナはここでコード量を節約し、あなたの関数がデザイナを必要としないときに@logを直接削除すればいいことがわかります.エディタでグローバルに検索して削除するだけでいいです.速くて便利で、自分でprintの文を探したり削除したりする必要はありません.
3、装飾器の原理
前の段落では、「log関数は装飾器」という言葉に気づいたかもしれません.そう、アクセサリーは関数です.
次に、装飾器がどのように作られたのかを探って、装飾器の原理を直感的に感じてみましょう.
まず、さっきの「Start」追加の問題に戻ります.
もしあなたがまだ装飾器を知らないとしたら.
Solutionで表示されます.
S 1関数にprint文を直接追加するよりも良い解決策があります!
そこであなたはこうしました.
def a():

    pass

def b():

    pass

def c():

    pass

def main():

    print 'Start a'
    a()
    print 'Start b'
    b()
    print 'Start c'
    c()

これは間違いないような気がしますし、元の関数の修正も避けられますし、print文を手作業で削除するならもっと便利です.うん、ちょっと進歩して、いいですね.
S 2さっきのコードはブスだと思います.もう少し最適化してもいいですよ.
するとあなたはこう書きました.
def a():

    pass

def b():

    pass

def c():

    pass

def decorator(func):

    print 'Start %s'% func
    func()

def main():

    decorator(a)
    decorator(b)
    decorator(c)

各関数にprint文を書く代わりに関数を書いて、時間を節約したようです.
しかし、このような状況が発生します.
def main():

    decorator(a)
    m = decorator(b)
    n = decorator(c) + m
    for i in decorator(d):
        i = i + n
    ......

さあ、decoratorを見て気絶しないと言ってください.大きな声で言え!
S 3あなたはまたもっと良い方法を考えました.
するとあなたはこう書きました.
def a():

    pass

def b():

    pass

def c():

    pass

def decorator(func):

    print 'Start %s' % func
    return func

a = decorator(a)

b = decorator(b)

c = decorator(c)

def main():

    a()
    b()
    c()

これでやっと名前を取り戻したので、気絶しません.もしa、b、cの3つの関数がパラメータを持っていたら、私はどうすればいいですか?!
このように書くのは絶対にだめです.
a = decorator(a(arg))
このときdecoratorでパラメータオブジェクトとすべきaに括弧を付けた,すなわち,aが括弧で実行された!あなたはただaが関数オブジェクトの形で存在したいだけで、おとなしくdecoratorの中に行ってパラメータにすればいいです.それを実行するのはあなたの本意ではありません.
どうすればいいの?
S 4次のコードをすばやく書いてください.
def a(arg):

    pass

def b(arg):

    pass

def c(arg):

    pass

def decorator(func):

    def wrapper(*arg, **kw)
        print 'Start %s' % func
        return func(*arg, **kw)
    return wrapper

a = decorator(a)

b = decorator(b)

c = decorator(c)

def main():

    a(arg)
    b(arg)
    c(arg)

decorator関数はwrapperを返し、wrapperは関数オブジェクトです.a=decorator(a)はaをwrapperに向けたもので、wrapperにはパラメータがあるので、変数aにもパラメータがある!