2016-04-05 18 views
3

以下のデコレータデモンストレーションコードがあります。明示的にgreet関数を呼び出さずに実行すると、print文がデコレータ関数内で実行され、Inside decoratorが出力されます。Pythonデコレータ関数の実行

私はこのデコレータの動作を理解できません。 greetを呼び出さなくても、time_decoratorがどのように呼び出されますか?私は、Python 3を使用しています

def time_decorator(original_func): 
    print('Inside decorator') 
    def wrapper(*args, **kwargs): 
     start = time.clock() 
     result = original_func(*args, **kwargs) 
     end = time.clock() 
     print('{0} is executed in {1}'.format(original_func.__name__, end-start)) 
     return result 
    return wrapper 


@time_decorator 
def greet(name): 
    return 'Hello {0}'.format(name) 

答えて

1
ない ランタイム で、スタート(プログラムが起動するPythonインタプリタがコードを読み取る)時間で呼び出され

デコレータ(とき装飾された関数は実際に呼び出されます)

実行時に、ラップされた関数wrapperが呼び出され、which自体が装飾された関数を呼び出し、その結果を返します。

したがって、print行が実行されることは全く正常です。

10個の関数を装飾すると、印刷出力の10倍が表示されます。このために装飾された関数を呼び出す必要はありません。

printwrapperに移動してください。これはもう発生しません。

Decoratorsならびにmetaclassesメタプログラミング(既存のコードからコードを作成/修正)と呼ばれるものの一部です。これは、理解するのに時間がかかりますが、驚くべき可能性を提供するプログラミングの本当に魅力的な側面です。

+0

ありがとう@Apero!コンパイル時にデコレータを呼び出す背景には何がありますか?デコレータとは別に、コンパイル時に呼び出されるオブジェクトはありますか? –

+0

はい、メタクラスは、実行時ではなく、コンパイル時に「メタクラス化」するクラスも変更します。メタクラスやデコレータは、初期コード自体を変更することなく、それぞれメタクラスやデコレートするコードを変更するため、コードハッキングのように見えます。この「今すぐコード」が呼び出されるたびに、新しいハッキングされた動作が発生します。 –

+0

私は「コンパイル時」と言っているのはむしろ誤解を招くと思います。 Pythonの関数(およびクラス)定義は、実行時(例えば、プログラムを起動するとき)にインタプリタによって実行されるステートメントによって作成されます。Pythonコード(ソースコードからバイトコードに変換される)にはコンパイルのステップが含まれていますが、これは 'def'のようなステートメントの実行とは関係ありません。 – Blckknght

4

time_decoratorは、機能装飾の間に実行される。である。 wrapperはありません(これは、greet()が呼び出されたときに呼び出される関数です)。

@は構文的な砂糖です。次のコードスニペットは同等です。

デコレータ構文:

@time_decorator 
def greet(name): 
    return 'Hello {0}'.format(name) 

明示的な装飾プロセス - デコレータは、別のものに基づいて、新しい機能を返す関数です。

def greet(name): 
    return 'Hello {0}'.format(name) 

greet = time_decorator(greet) 
関連する問題