2016-10-11 4 views
0

私がデコレータについて少し再探索していたとき、私は多少の混乱を招くコードを見つけました。Python:オブジェクトとしての関数の混乱例

def get_text(name): 
    return "lorem ipsum, {0} dolor sit amet".format(name) 

def p_decorate(func): 
    def func_wrapper(name): 
     return "<p>{0}</p>".format(func(name)) 
    return func_wrapper 

my_get_text = p_decorate(get_text) 

print my_get_text("John") 

# <p>Outputs lorem ipsum, John dolor sit amet</p> 

私は(クール)変数と関数を渡すの概念はしかし、それが複数回通過された方法は私を混乱理解しています。 my_get_textはすでに引数を持つ関数(別の関数)に割り当てられています。しかし、その直後にこの新しい変数を参照し、引数を渡します( "John")。 「ジョン」がfunc_wrapper()に転送される方法も難解です。

my_get_textはもっと多くの引数を受け取ることができ、内部関数にはどのように渡されますか?

これはデコレータがどのように動作するかのデモンストレーションであるあなた

+2

コードのインデントを修正してください。インデントはPythonで意味を持ち、一般には推測できません。 –

+0

'p_decorate()'は何を返しますか(もちろん、インデントが修正されたら)? –

+0

また、この例で何が起きているのかを完全に理解するために、_closure_の概念を理解する必要があります。 –

答えて

2

ありがとう:彼らは基本的に別の内部関数に装飾された機能をラップし、その参照を返します。あなたの例では

  1. 、パラメータ(get_text)として巻き付け可能機能を持つ関数を呼び出すp_decoratemy_get_text = p_decorate(get_text)コール。
  2. 戻り値は、パラメータnameを1つだけ使用する、新しく定義された関数への参照です。この戻り値は変数名に割り当てられます。my_get_text
  3. my_get_textは、の呼び出し可能なです。関数参照であるためです。
  4. my_get_textを呼び出すと、デコレータによって作成された関数が呼び出され、パラメータname(ケース'John')が渡されます。
  5. この関数は、<p> -Tagsを作成し、それらの間に文字列をプッシュします。この文字列は、手順1でデコレータを指定した関数呼び出しから取得されます。と飾られた呼び出しの戻り値です。関数func_wrapper関数が装飾されるたびに再定義されているためところで

、(閉鎖を参照)、戻り値は、全く新しい機能を指す関数リファレンスです。
は、メモリアドレスを比較する:関数が非常に同じ呼び出しで定義され

a = p_decorate(get_text) 
b = p_decorate(get_text) 
print(a == b) 
print(a) 
print(b) 

>>> False 
>>> <function func_wrapper at 0x02ADFF30> 
>>> <function func_wrapper at 0x02ADFF70> 

、彼らはクロージャあるので、関数ポインタは、他のメモリアドレス(すなわち、異なる機能)を指します。