Python語言特性-面向切面程式設計AOP
阿新 • • 發佈:2018-12-14
我們先來解釋一下AOP的概念。
AOP概念及作用
AOP 即面向切面程式設計,指擴充套件功能不修改原始碼,將功能程式碼從業務邏輯程式碼中分離出來。
主要作用就是將類似於日誌記錄,效能統計,安全控制,事務處理,異常處理等重複性的程式碼塊從業務邏輯程式碼中劃分出來,對這些行為的分離。並且將它們獨立到非知道業務邏輯的方法中,從而做到改變這些行為的時候不影響業務邏輯程式碼。
裝飾器實現AOP
我們python中使用裝飾器實現AOP。裝飾器是一個很著名的設計模式,經常被用於有切面需求的場景,裝飾器的作用就是為已經存在的物件新增額外的功能。
裝飾器及閉包簡介
裝飾器 本身也是一個函式 ,這個函式以閉包的形式定義,在使用這個裝飾器函式時,在被裝飾的函式的前一行,使用 @裝飾器函式名 形式來裝飾。
閉包是指在一個函式中定義了一個另外一個函式,內函式裡運用了外函式的臨時變數,並且外函式的返回值是內函式的引用,這樣就構成了一個閉包。 閉包的使用,可以隱藏內部函式的工作細節,只給外部使用者提供一個可以執行的內部函式的引用。
裝飾器例項應用
寫一個功能函式,實現一百萬次的累加
def my_count():
s = 0
for i in range(1000001):
s += i
print('sum : ', s)
裝飾器實現
import time def count_time(func): def wrapper(): #wrapper 裝飾 start = time.time() func() end = time.time() print('共計執行:%s 秒'%(end - start)) # 使用%d顯示,取整後是0秒,因為不到一秒 return wrapper @count_time # 這實際就相當於解決方法3中的 my_count = count_tiem(my_count) def my_count(): s = 0 for i in range(10000001): s += i print('sum : ', s) my_count()
這樣實現的好處是,定義好了閉包函式後。只需要通過 @xxx 形式的裝飾器語法,將 @xxx 加到要裝飾的函式前即可。使用者在使用時,根本不需要知道被裝飾了。只需要知道原來的函式功能是什麼即可。
在執行 @xxx 時 ,實際就是將 原函式傳遞到閉包中,然後原函式的引用指向閉包返回的裝飾過的內部函式的引用。
類實現裝飾器
在類中通過使用 init 和 __call__方法來實現
class Test(object): # 通過初始化方法,將要被裝飾的函式傳進來並記錄下來 def __init__(self, func): self.__func = func # 重寫 __call__ 方法來實現裝飾內容 def __call__(self, *args, **kwargs): print('wrapper context') self.__func(*args, **kwargs) # 實際通過類的魔法方法call來實現 @Test # --> show = Test(show) show由原來引用函式,裝飾後變成引用Test裝飾類的物件 def show(): pass show() # 物件呼叫方法,實際上是呼叫魔法方法call,實現了裝飾器
函式被多個裝飾器所裝飾
一個函式在使用時,通過一個裝飾器來擴充套件,可能並不能完成達到預期。
Python 中允許一個函式被多個裝飾器所裝飾。
# 裝飾器1
def setFunc1(func):
def wrapper1(*args, **kwargs):
print('Wrapper Context 1 Start...')
func(args, kwargs)
print('Wrapper Context 1 End...')
return wrapper
# 裝飾器2
def setFunc2(func):
def wrapper2(*args, **kwargs):
print('Wrapper Context 2 Start...')
func(args, kwargs)
print('Wrapper Context 2 End...')
return wrapper
#一個函式被裝飾了兩次
@setFunc1
@setFunc2
def show(*args, **kwargs):
print('Show Run ...')
show()
執行結果
Wrapper Context 1 Start...
Wrapper Context 2 Start...
Show Run ...
Wrapper Context 2 End...
Wrapper Context 1 End...
這個裝飾器是從上到下執行,從下向上裝飾,
在web框架中的鉤子函式和中介軟體都有使用。
總結
- 函式可以像普通變數一樣,做為函式的引數或返回值進行傳遞。
- 函式內部可以定義另外一個函式,這樣做的目的可以隱藏函式功能的實現。
- 閉包實際也是一種函式定義形式。
- 閉包定義規則是在外部函式中定義一個內部函式,內部函式使用外部函式的變數,並返回內部函式的引用。
- 裝飾器的作用是在不改變現有函式基礎上,為函式增加功能。
- 通過在已有函式前,通過@閉包函式名的形式來給已有函式新增裝飾器。
- 一個裝飾器可以為多個函式提供裝飾功能,只需要在被裝飾的函式前加 @xxx 即可。
- 通過類也可以實現裝飾器效果,需要重寫 init 和 call 函式。
- 類實現的裝飾器在裝飾函式後,原來的函式引用不在是函式,而是裝飾類的物件。
- 一個函式也可以被多個裝飾器所裝飾。