Python學習筆記 函式式程式設計 裝飾器

2021-07-14 17:33:18 字數 3278 閱讀 1321

【根據廖雪峰python教程整理】

由於函式也是乙個物件,而且函式物件可以被賦值給變數,所以,通過變數也能呼叫該函式。

>>> def now():

...     print '2013-12-25'

...>>> f = now

>>> f()

2013-12-25

函式物件有乙個__name__

屬性,可以拿到函式的名字:

>>> now.__name__

'now'

>>> f.__name__

'now'

現在,假設我們要增強now()

函式的功能,比如,在函式呼叫前後自動列印日誌,但又不希望修改

now()

函式的定義,這種在**執行期間動態增加功能的方式,稱之為「裝飾器」(decorator

本質上,decorator

就是乙個返回函式的高階函式。所以,我們要定義乙個能列印日誌的

decorator

,可以定義如下:

def log(func):

print 'call %s():' % func.__name__

return func(*args, **kw)

觀察上面的log

,因為它是乙個

decorator

,所以接受乙個函式作為引數,並返回乙個函式。我們要借助

python的@

語法,把

decorator

置於函式的定義處:

@log

def now():

print '2013-12-25'

呼叫now()

函式,不僅會執行

now()

函式本身,還會在執行

now()

函式前列印一行日誌:

>>> now()

call now():

2013-12-25

把@log

放到now()

函式的定義處,相當於執行了語句:

now = log(now)

由於log()

是乙個decorator

,返回乙個函式,所以,原來的

now()

函式仍然存在,只是現在同名的

now變數指向了新的函式,於是呼叫

now()

將執行新函式,即在

log()

函式中返回的

函式。

(*args, **kw)

,因此,

函式可以接受任意引數的呼叫。在

函式內,首先列印日誌,再緊接著呼叫原始函式。

如果decorator

本身需要傳入引數,那就需要編寫乙個返回

decorator

的高階函式,寫出來會更複雜。比如,要自定義

log的文字:

def log(text):

def decorator(func):

print '%s %s():' % (text, func.__name__)

return func(*args, **kw)

return decorator

這個3層巢狀的

decorator

用法如下:

@log('execute')

def now():

print '2013-12-25'

執行結果如下:

>>> now()

execute now():

2013-12-25

和兩層巢狀的decorator

相比,3

層巢狀的效果是這樣的:

>>> now = log('execute')(now)

我們來剖析上面的語句,首先執行log('execute')

,返回的是

decorator

函式,再呼叫返回的函式,引數是

now函式,返回值最終是

函式。

以上兩種decorator

的定義都沒有問題,但還差最後一步。因為我們講了函式也是物件,它有

__name__

等屬性,但你去看經過

decorator

裝飾之後的函式,它們的

__name__

已經從原來的

'now'

變成了:

>>> now.__name__

函式名字就是

,所以,需要把原始函式的

__name__

等屬性複製到

函式中,否則,有些依賴函式簽名的**執行就會出錯。

這樣的**,

python

內建的functools.wraps

就是幹這個事的,所以,乙個完整的

decorator

的寫法如下:

import functools

def log(func):

@functools.wraps(func)

print 'call %s():' % func.__name__

return func(*args, **kw)

或者針對帶引數的decorator

:import functools

def log(text):

def decorator(func):

@functools.wraps(func)

print '%s %s():' % (text, func.__name__)

return func(*args, **kw)

return decorator

import functools是匯入

functools

模組。模組的概念稍候講解。現在,只需記住在定義

的前面加上

@functools.wraps(func)

即可。

小結:

在物件導向(oop

)的設計模式中,

decorator

被稱為裝飾模式。

oop的裝飾模式需要通過繼承和組合來實現,而

python

除了能支援

oop的

decorator

外,直接從語法層次支援

decorator

。python

的decorator

可以用函式實現,也可以用類實現。

decorator可以增強函式的功能,定義起來雖然有點複雜,但使用起來非常靈活和方便。

Python學習筆記 函式式程式設計 高階函式

根據廖雪峰python教程整理 高階函式英文叫higher order function 什麼是高階函式?我們以實際 為例子,一步一步深入概念。一 變數可以指向函式 以python 內建的求絕對值的函式 abs 為例,呼叫該函式用以下 abs 10 10 但是,如果只寫abs 呢?abs 可見,ab...

Python學習筆記之 函式式程式設計

函式式程式設計的乙個特點就是,允許把函式本身作為引數傳入另乙個函式,還允許返回乙個函式。變數可以指向函式 f abs f 10 10函式名也是變數 abs 10 abs 10 traceback most recent call last file line 1,in typeerror int o...

python學習筆記(四) 函式式程式設計

1 高階函式 高階函式 higher order function 1 變數可以指向函式 函式本身也可以賦值給變數。2 函式名也是變數 指向函式的變數。3 傳入函式 變數能夠指向函式,函式的引數能接收變數,乙個函式就可以接收另乙個函式作為引數。接收兩個引數 函式,iterable map 將傳入的函...