相信學過java框架的對AOP應該是很熟悉了,那什么是面向切面編程AOP呢?
AOP
簡言之、這種在運行時,編譯時,類和方法加載時,動態(tài)地將代碼切入到類的指定方法、指定位置上的編程思想就是面向切面的編程。
我們管切入到指定類指定方法的代碼片段稱為切面,而切入到哪些類、哪些方法則叫切入點。有了AOP,我們就可以把幾個類共有的代碼,抽取到一個切片中,等到需要時再切入對象中去,從而改變其原有的行為。
優(yōu)點是:這樣的做法,對原有代碼毫無入侵性
裝飾器
裝飾器是一個很著名的設計模式,經(jīng)常被用于有切面需求的場景,較為經(jīng)典的有插入日志、性能測試、事務處理等。裝飾器是解決這類問題的絕佳設計,有了裝飾器,我們就可以抽離出大量函數(shù)中與函數(shù)功能本身無關的雷同代碼并繼續(xù)重用。
概括的講,裝飾器的作用就是為已經(jīng)存在的對象添加額外的功能。
要想明白裝飾器首先要明白一個概念即函數(shù)即是對象。
不明白的可以看看這篇文章
函數(shù)就是對象.因此,對象:
- 可以賦值給一個變量
- 可以在其他函數(shù)里定義
- 函數(shù)可以返回另一個函數(shù)
- 函數(shù)作為參數(shù)傳遞
自己動手實現(xiàn)裝飾器
# 裝飾器就是把其他函數(shù)作為參數(shù)的函數(shù)
def my_new_decorator(a_function_to_decorate):
# 在函數(shù)里面,裝飾器在運行中定義函數(shù): 包裝.
# 這個函數(shù)將被包裝在原始函數(shù)的外面,所以可以在原始函數(shù)之前和之后執(zhí)行其他代碼..
def the_wrapper_function():
# 把要在原始函數(shù)被調(diào)用前的代碼放在這里
print "Before the function runs"
# 調(diào)用原始函數(shù)(用括號)
a_function_to_decorate()
# 把要在原始函數(shù)調(diào)用后的代碼放在這里
print "After the function runs"
# 在這里"a_function_to_decorate" 函數(shù)永遠不會被執(zhí)行
# 在這里返回剛才包裝過的函數(shù)
# 在包裝函數(shù)里包含要在原始函數(shù)前后執(zhí)行的代碼.
return the_wrapper_function
# 加入你建了個函數(shù),不想修改了
def a_stand_alone_function():
print "I am a stand alone function, don't you dare modify me"
a_stand_alone_function()
#輸出: I am a stand alone function, don't you dare modify me
# 現(xiàn)在,你可以裝飾它來增加它的功能
# 把它傳遞給裝飾器,它就會返回一個被包裝過的函數(shù).
a_function_decorated = my_new_decorator(a_stand_alone_function)
# 執(zhí)行
a_function_decorated()
#輸出s:
#Before the function runs
#I am a stand alone function, don't you dare modify me
#After the function runs
真實裝飾器
@my_new_decorator
def another_stand_alone_function():
print "Leave me alone"
another_stand_alone_function()
#輸出:
#Before the function runs
#Leave me alone
#After the function runs
從這里可以看出@decorator就是下面的簡寫:
another_stand_alone_function = my_new_decorator(another_stand_alone_function)
在裝飾器函數(shù)里傳入?yún)?shù)
def a_decorator_passing_arguments(function_to_decorate):
def a_wrapper_accepting_arguments(arg1, arg2):
print "I got args! Look:", arg1, arg2
function_to_decorate(arg1, arg2)
return a_wrapper_accepting_arguments
# 當你調(diào)用裝飾器返回的函數(shù)時,也就調(diào)用了包裝器,把參數(shù)傳入包裝器里,
# 它將把參數(shù)傳遞給被裝飾的函數(shù)里.
@a_decorator_passing_arguments
def print_full_name(first_name, last_name):
print "My name is", first_name, last_name
print_full_name("Peter", "Venkman")
# 輸出:
#I got args! Look: Peter Venkman
#My name is Peter Venkman
把參數(shù)傳給裝飾器
# 裝飾器就是一個'平常不過'的函數(shù)
def my_decorator(func):
print "I am an ordinary function"
def wrapper():
print "I am function returned by the decorator"
func()
return wrapper
# 因此你可以不用"@"也可以調(diào)用他
def lazy_function():
print "zzzzzzzz"
decorated_function = my_decorator(lazy_function)
#輸出: I am an ordinary function
# 之所以輸出 "I am an ordinary function"是因為你調(diào)用了函數(shù),
# 并非什么魔法.
@my_decorator
def lazy_function():
print "zzzzzzzz"
#輸出: I am an ordinary function
這里調(diào)用decorated_function()才會輸出裝飾器里面的方法,建一個裝飾器.它只是一個新函數(shù),去掉中間變量他就會變?yōu)檎嬲难b飾器,那么如何去掉中間變量
def decorator_maker_with_arguments(decorator_arg1, decorator_arg2):
print "I make decorators! And I accept arguments:", decorator_arg1, decorator_arg2
def my_decorator(func):
# 這里傳遞參數(shù)的能力是借鑒了 closures.
# 如果對closures感到困惑可以看看下面這個:
# http://stackoverflow.com/questions/13857/can-you-explain-closures-as-they-relate-to-python
print "I am the decorator. Somehow you passed me arguments:", decorator_arg1, decorator_arg2
# 不要忘了裝飾器參數(shù)和函數(shù)參數(shù)!
def wrapped(function_arg1, function_arg2) :
print ("I am the wrapper around the decorated function.\n"
"I can access all the variables\n"
"\t- from the decorator: {0} {1}\n"
"\t- from the function call: {2} {3}\n"
"Then I can pass them to the decorated function"
.format(decorator_arg1, decorator_arg2,
function_arg1, function_arg2))
return func(function_arg1, function_arg2)
return wrapped
return my_decorator
@decorator_maker_with_arguments("Leonard", "Sheldon")
def decorated_function_with_arguments(function_arg1, function_arg2):
print ("I am the decorated function and only knows about my arguments: {0}"
" {1}".format(function_arg1, function_arg2))
decorated_function_with_arguments("Rajesh", "Howard")
#輸出:
#I make decorators! And I accept arguments: Leonard Sheldon
#I am the decorator. Somehow you passed me arguments: Leonard Sheldon
#I am the wrapper around the decorated function.
#I can access all the variables
# - from the decorator: Leonard Sheldon
# - from the function call: Rajesh Howard
#Then I can pass them to the decorated function
#I am the decorated function and only knows about my arguments: Rajesh Howard
看到了嗎?我們用一個函數(shù)調(diào)用"@“
幾個例子
def addTips(fun):
def wrap(*arg,**kwargs):
print("this is oper before")
result = fun(*arg,**kwargs)
#return result
print("this is oper after")
return result
return wrap
@addTips
def add():
print("進行添加的操作")
add()
this is oper before
進行添加的操作
this is oper after
@addTips
def add1(x,y):
print(x+y)
add1(2,6)
this is oper before
8
this is oper after
@addTips
def add2(x,y):
return x+y
print(add2(2,3))
this is oper before
this is oper after
5
def addTips(i):
def wrap1(fun):
def wrap(*arg,**kwargs):
print("this is oper before")
result = 0
if i > 10:
result = fun(*arg,**kwargs)
else:
print("you not have any auth")
#return result
print("this is oper after")
return result
return wrap
return wrap1
@addTips(11)
def add(x,y):
print(x+y)
add(2,3)
this is oper before
5
this is oper after
裝飾器的知識點
裝飾器使函數(shù)調(diào)用變慢了.一定要記住.
裝飾器不能被取消(有些人把裝飾器做成可以移除的但是沒有人會用)所以一旦一個函數(shù)被裝飾了.所有的代碼都會被裝飾.
Python自身提供了幾個裝飾器,像property, staticmethod.
Django用裝飾器管理緩存和試圖的權限.
Twisted用來修改異步函數(shù)的調(diào)用.