#!/usr/bin/python**加粗文字**
def deco_functionNeedDoc(func):
if func.__doc__ == None:
print func,"has no __doc__, it's a bad habit."
else:
print func,':',func.__doc__,'.'
return func
@deco_functionNeedDoc
def f():
print 'f() Do something'
@deco_functionNeedDoc
def g():
'I have a __doc__'
print 'g() Do something'
f()
g()
Actual Result:
<function f at 0x7f31e65d05f0> has no __doc__, it's a bad habit.
<function g at 0x7f31e65d0668> : I have a doc .
f() Do something
g() Do something
Expected Result:
<function f at 0x7f31e65d05f0> has no __doc__, it's a bad habit.
f() Do something
<function g at 0x7f31e65d0668> : I have a doc .
g() Do something
f()和g()被修饰后是如何执行的?
另外一段使用装饰器的代码
#-*- coding: UTF-8 -*-
import time
def timeit(func):
def wrapper():
start = time.clock()
func()
end =time.clock()
print 'used:', end - start
return wrapper
@timeit
def foo():
print 'in foo()'
foo()
Actual Result:
in foo()
used: 2.1e-05
这一段使用wrapper方法执行时先执行foo(),再执行wrapper()。
加了wrapper会有什么差别吗?
デコレータは、「コンパイル時に」実行されるプログラムに似ています。元の関数がメモリにロードされる前でも関数を「装飾」します。そのため、最初に装飾されてから関数が実行される装飾プログラムを次に示します。それ以外の場合は、最後に f() または g() を実行せずに、装飾された関数内のコードの実行を試みることができます
関数はデコレーターを通過した後に再バインドされます。つまり
リーリーつまり、デコレーターは関数オブジェクトの一部である必要があります。言い換えると、このステップは、コードがコンパイル中に「ハードコーディング」されること、つまり、バイトコードにコンパイルされるときに行われます。関数の
リーリーそれらはすべてコンパイル段階で決定されます。つまり、コードはコンパイル段階で最初にデコレーターが実行されて関数が再バインドされ、次に実行段階で f 内のものが直接実行されます。
PS: デコレータの例は一般的ではありませんが、元の関数をラップしているものも見つかります
上記は私の個人的な理解です。一緒に議論しましょう
変更された
リーリーwrap
デコレーター関数は、実際には最初に実行されるtimeit
関数ですが、何も出力せず、関数オブジェクトを直接返します。たとえば、次のように追加すると、出力が変更され、最初に
ですI am timeit
が出力されます。上で述べたことを見てください。デコレーターは関数を再バインドし、別の関数を返します。コンパイル中に完了し、再度実行すると新しい関数が直接実行されます。それがあなたのwrapper