裝飾器
由於函式也是乙個物件,而且函式物件可以被賦值給變數,所以,通過變數也能呼叫該函式。
>>> defnow():
print('
2019.0519
')
>>> f =now()
2019.0519
>>> f =now
>>>f()
2019.0519
函式物件有乙個__name__
屬性,可以拿到函式的名字:
>>> now.__name__'now
'>>> f.__name__
'now
'
現在,假設我們要增強now()
函式的功能,比如,在函式呼叫前後自動列印日誌,但又不希望修改now()
函式的定義,這種在**執行期間動態增加功能的方式,稱之為「裝飾器」(decorator)。
本質上,decorator就是乙個返回函式的高階函式。所以,我們要定義乙個能列印日誌的decorator,可以定義如下:
>>> deflog(func):
print('
cll %s():
' % func.__name__
)
return func(*args,**kw)
觀察上面的
log
,因為它是乙個decorator,所以接受乙個函式作為引數,並返回乙個函式。我們要借助python的@語法,把decorator置於函式的定義處:>>>@log
defnow():
print('
2019.0519
')
呼叫now()
函式,不僅會執行now()
函式本身,還會在執行now()
函式前列印一行日誌
>>>now()call now():
2019.0519
把@log
放到now()
函式的定義處,相當於執行了語句:
now =log(now)如果decorator本身需要傳入引數,那就需要編寫乙個返回decorator的高階函式,寫出來會更複雜。比如,要自定義log的文字:>>>now()
cll now():
2019.0519
>>> now.__name__
>>> deflog(text):
defdecorator(func):
print('
%s %s()
' %(text,func.__name__
))
return func(*args,**kw)
return
return
decorator
>>> @log('
我的函式')
defnow():
print('
2019.0519')
>>>now()
我的函式 now()
2019.0519
這個3層巢狀的decorator用法如下:
>>> @log('我的函式')
defnow():
print('
2019.0519
')
執行結果如下:
>>>now()我的函式 now()
2019.0519
和兩層巢狀的decorator相比,3層巢狀的效果是這樣的:
>>> now = log('execute
')(now)
>>> now.__name__''
'__name__ = func.__name__這樣的**
,python內建的functools.wraps就是幹這個事的,所以,乙個完整的decorator的寫法如下:
import
functools
deflog(func):
@functools.wraps(func)
'call %s():
' % func.__name__
return func(*args, **kw)
return
或者針對帶引數的decorator:
import
functools
deflog(text):
defdecorator(func):
@functools.wraps(func)
'%s %s():
' % (text, func.__name__
)
return func(*args, **kw)
return
return
decorator
小結在物件導向(oop)的設計模式中,decorator被稱為裝飾模式。oop的裝飾模式需要通過繼承和組合來實現,而python除了能支援oop的decorator外,直接從語法層次支援decorator。python的decorator可以用函式實現,也可以用類實現。
decorator可以增強函式的功能,定義起來雖然有點複雜,但使用起來非常靈活和方便。
請編寫乙個decorator,能在函式呼叫的前後列印出
'begin call
'和'end call
'的日誌。
再思考一下能否寫出乙個@log的decorator,使它既支援:
@log
deff():
pass
又支援:
@log(
'execute')
deff():
pass
寫法如下:
Vue2 0學習之路
一 基礎 1.vue2.0學習記錄 hello world 2.vue2.0學習記錄 todo list初步 3.vue2.0學習記錄 mvvm模式 4.vue2.0學習記錄 全域性元件 5.vue2.0學習記錄 區域性元件 6.vue2.0學習記錄 父子元件傳值 7.vue2.0學習記錄 生命週期...
Python學習之路
python 十分鐘入門 python 菜鳥教程 pycharm安裝numpy python 檔案讀取 with open xml path,r as fr content fr.read python讀取檔案時提示 unicodedecodeerror gbk codec can t decode...
python學習之路
簡單理解下,yield可以先看作 return 直接返回某個值,返回之後程式就不再往下執行了。看做return之後再把它看做乙個是生成器 generator 的一部分 帶yield的函式才是真正的迭代器 def foo print starting.while true res yield 4pri...