python 装饰器执行顺序
阿神
阿神 2017-04-17 17:38:40
0
2
333
#!/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会有什么差别吗?

阿神
阿神

闭关修行中......

全部回覆(2)
洪涛

裝飾器更像是「編譯時」所執行的程序,即使在原函數還未裝載入內存前就先為函數進行「裝飾」工作,所以這裡是先進行裝飾,再運行的裝飾後的函數。不然,你試試在最後不執行f()、g()同樣可以執行裝飾函數裡面的程式碼

洪涛

python是一種半編譯半解釋型運行行環境。首先會將原始碼編譯為字節碼,然後再執行這些字節碼以獲得結果。

函數經過裝飾器就被重新綁定了,也就是說

f = deco_functionNeedDoc(f)

所以裝飾器應該是屬於函數物件的一部分, 也就是說這一步是程式碼在編譯時期,也就是編譯為字節碼的時候,就固定"寫死"了,這個類似與函數的預設參數

def func(a = []):
    pass

都是在編譯階段就把就確定了。所以說咯,你的程式碼確定解釋通啦, 在編譯階段先就執行裝飾器重新綁定函數,然後執行階段就直接運行f裡面的東西。
PS:你這個裝飾器的例子不太典型,可以找一些對原函數做了wrap的那種
以上是個人理解,共同討論


修改之後的wrap裝飾器函數, 其實也是先執行的timeit這個函數,只不過沒有輸出東西,而是直接回傳了一個函數物件而已。例如你這樣加一句:wrap装饰器函数, 其实也是先执行的timeit这个函数,只不过没有输出东西,而是直接返回了一个函数对象而已。比如你这样加一句:


#-*- coding: UTF-8 -*-  
import time

def timeit(func):
    def wrapper():
        start = time.clock()
        func()
        end =time.clock()
        print 'used:', end - start
    print 'I am timeit'
    return wrapper

@timeit
def foo():
    print 'in foo()'

foo()

输出就会变了,先输出I am timeit. 你再看看我上面说的,装饰器就是把函数重新绑定,返回另一个函数。 是在编译时期完成的, 再执行的时候,直接执行新函数。也就是你的wrapper rrreee

輸出就會變了,先輸出I am timeit. 你再看看我上面說的,裝飾器就是把函數重新綁定,回傳另一個函數。 是在編譯時期完成的, 再執行的時候,直接執行新函數。也就是你的wrapper🎜
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板