函式式程式設計(五) 裝飾器

2021-08-20 18:36:17 字數 2657 閱讀 2365

假設我們要增強now()函式的功能,比如,在函式呼叫前後自動列印日誌,但又不希望修改now()函式的定義,這種在**執行期間動態增加功能的方式,稱之為「裝飾器」(decorator)。---即為已經存在的物件新增額外的功能(為了減少重複寫**)。

裝飾器的需求場景:插入日誌、效能測試、事務處理、快取、許可權校驗等。

一、函式裝飾器

1、裝飾器的擴充套件功能**寫在什麼地方

本質上,decorator就是乙個返回函式的高階函式。所以,我們要定義乙個能列印日誌的decorator,可以定義如下:

def

log(func):

def(*args, **kw):

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

#裝飾器的功能擴充套件**區

return

func(*args, **kw)

return

2、@符號的作用

@符號是裝飾器的語法糖,在定義函式的時候使用,避免再一次賦值操作。相當於執行了語句:

now = log(now)

觀察上面的log,因為它是乙個decorator,所以接受乙個函式作為引數,並返回乙個函式。我們要借助python的@語法,把decorator置於函式的定義處:

@log         

#相當於在定義函式now()之後,執行一條命令:now=log(now)

defnow

():

print(

'2015-3-25'

)

呼叫now()函式,不僅會執行now()函式本身,還會在執行now()函式前列印一行日誌:

>>> now()

call now():

2015-3-25

@log放到now()函式的定義處

now = log(now)

3、裝飾器中的函式與原函式之間的關係

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

由於log()是乙個decorator,返回乙個函式,所以,

原來的now()函式仍然存在,只是現在同名的now變數指向了新的函式,於是呼叫now()將執行新函式,

二、帶引數的裝飾器

裝飾器的語法允許我們在呼叫時,提供其它引數,比如@decorator(x),這樣,就為裝飾器的編寫和使用提供了更大的靈活性。它實際上是對原有裝飾器的乙個函式封裝,並返回乙個裝飾器。我們可以將它理解為乙個含有引數的閉包。

三、類裝飾器

類裝飾器具有靈活度大、高內聚、封裝性等優點。使用類裝飾器還可以依靠類內部的__call__方法,當使用@形式將裝飾器附加到函式上時,就會呼叫此方法。

四、內建裝飾器

@a@b

@cdef f()

等效於f=a(b(c(f)))

五、缺點

使用裝飾器極大地復用了**,但是他有乙個缺點就是原函式的元資訊不見了,比如函式的

docstring

、__name__

、引數列表

。不需要編寫

這樣的**,python內建的functools.wraps就是幹這個事的,所以,乙個完整的decorator的寫法如下:

import

functools

deflog

(func):

@functools.wraps(func)

#functools本身也是個裝飾器,它保證原有函式的相關屬性不被wraps這個函式取代而發生不會發生變化的問題出現

def(*args, **kw):

print(

'call %s():'

% func.__name__)

return

func(*args, **kw)

return

或者針對帶引數的decorator:

import functools

deflog

(text):

defdecorator

(func):

@functools.wraps(func)

def(*args, **kw):

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

return func(*args, **kw)

return decorator

即可。

函式式程式設計(4) 裝飾器

裝飾器 由於函式也是乙個物件,而且函式物件可以被賦值給變數,所以,通過變數也能呼叫該函式。def now print 2013 12 25 f now f 2013 12 25 函式物件有乙個 name 屬性,可以拿到函式的名字 now.name now f.name now 現在,假設我們要增強n...

python 函式式程式設計 高階函式 裝飾器

coding gb2312 coding utf 8 高階函式 import math def is sqr x y int math.sqrt x return x y y print filter is sqr,range 1,101 返回函式 作用 延遲執行 def calc prod lst...

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

根據廖雪峰python教程整理 由於函式也是乙個物件,而且函式物件可以被賦值給變數,所以,通過變數也能呼叫該函式。def now print 2013 12 25 f now f 2013 12 25 函式物件有乙個 name 屬性,可以拿到函式的名字 now.name now f.name now...