2017-03-10 11 views
2

私は現在デコレータを試していますが、私は一つのことを理解できません。今、私は(私が思う)すべてを理解ティルPython - 内部関数を呼び出すデコレータ?

>>> foo('Jon') 
Calling wrap() 
Jon 

def new_decorator(func): 
    print "Calling new_decorator()" 
    def wrap(arg): 
     print "Calling wrap()" 
     func(arg) 
    return wrap 

@new_decorator 
def foo(name): 
    print name 

我々が得る実行している時:

'Calling decorate()' 

のみfooを呼び出した後、私はシンプルなデコレータを持っています。開始時にnew_decorator(func)が呼び出され、fooがパラメータとして返され、wrapを返します。

def add_attr(varname, value): 
    def decorate(func): 
     print "Calling decorate()" 
     setattr(func, varname, value) 
     return func 
    return decorate 

@add_attr('var', 'New attribute') 
def foo(): 
    print "Calling foo()" 
    print foo.var 

foo()を呼び出すことなく)、それを実行していることが返されます:

'Calling decorate()' 

foo()後:

>>> foo() 
Calling foo() 
New attribute 

私は理解できない何かがあるしかし、今、私はパラメータでデコレータを試してみました、なぜこの "内部"関数decorateは、開始時にと呼ばれ、foo?最初の例ではそうではありませんでした。関数fooはどのようにしてdecorateにパラメータとして送信されましたか? add_attrは2つのパラメータしか取得せず、いずれもfooではありません。

+0

おそらくあなたは*コール*ですか?そのアイテムを呼び出す何かの周りに角括弧を追加した場合... –

+1

2番目のケースは、すでに内部飾りを呼び出す 'add_attr( 'var'、 'New attribute')(foo)'に似ています。 –

+0

@MosesKoledoye私はそれを得る、ありがとう! –

答えて

2

一般に、引数を受け入れるデコレータには3つのネスティングレイヤーが必要です。引数を "デコレータメーカ"として受け入れるデコレータを考えてみましょう。 と呼ばれるときにデコレータを返す必要があります。

@new_decorator 
def foo(name): 
    print name 

次のコードは本当にこのためだけの構文糖であることを考慮し、これを理解するには:だから

def foo(name): 
    print name 

foo = new_decorator(foo) 

は、同様に、この:

@add_attr('var', 'New attribute') 
def foo(): 
    print "Calling foo()" 
    print foo.var 

は同一ですこれまで:

def foo(): 
    print "Calling foo()" 
    print foo.var 

foo = add_attr('var', 'New attribute')(foo) 

これは正しい指示書でadd_attrを正しく導くはずです。

いくつか試してもまだ混乱している場合は、a famous answer from e-satisを参照してください。これは、デコレータをウェブで見たことよりも優れていると説明しています。

+0

ありがとう、今私はそれを得る! –

関連する問題