#!/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的那種
以上是個人理解,共同討論
修改之後的
wrap
裝飾器函數, 其實也是先執行的timeit
這個函數,只不過沒有輸出東西,而是直接回傳了一個函數物件而已。例如你這樣加一句:wrap
装饰器函数, 其实也是先执行的timeit
这个函数,只不过没有输出东西,而是直接返回了一个函数对象而已。比如你这样加一句:输出就会变了,先输出
輸出就會變了,先輸出I am timeit
. 你再看看我上面说的,装饰器就是把函数重新绑定,返回另一个函数。 是在编译时期完成的, 再执行的时候,直接执行新函数。也就是你的wrapper
rrreeeI am timeit
. 你再看看我上面說的,裝飾器就是把函數重新綁定,回傳另一個函數。 是在編譯時期完成的, 再執行的時候,直接執行新函數。也就是你的wrapper
🎜