Python裝飾器

裝飾器是一種用於封裝函數或類的代碼工具。它顯式的將封裝器應用到函數或類上,從而使它們選擇加入到裝飾器的功能中。閉包

裝飾器究其本質是一個接受可調用函數的可調用函數,並返回一個可調用函數。裝飾器是一個函數,該函數接受被裝飾的函數做爲其位置參數,裝飾器經過使用該參數來執行某些操做,而後返回原始參數或一些其餘的調用。模塊化

看下面的代碼,是一個簡單的裝飾器:函數

1 def decorated_by(func):
2     func.__doc__ += '\nDecorated by decorated_by.'
3     return func
4 
5 def add(x, y):
6     return x + y
7 
8 add = decorated_by(add)

在上面這段代碼中,decorated_by是裝飾器,add是被裝飾的函數,代碼的做用就是修改了add函數的__doc__屬性。工具

將被裝飾函數應用裝飾器通常寫做:spa

1 @decorated_by
2 def add(x, y):
3     return x + y

裝飾器實現的原理是什麼呢?裝飾器之因此可以實現是因爲Python的閉包。調試

再來看一段代碼:code

def func(a, b):
    x=a
    y=b
    def add():
        z=4
        return x+y+z
    return add

>>>add =  func(1, 2)
>>>add()
7

add是func的內部函數,在add的局部做用域中能夠直接訪問func局部做用域中定義的x, y變量。簡單的說,這種內部函數可使用外部函數變量的行爲,叫作閉包。
再來看一段代碼:blog

 1 def dec(func):
 2     def in_dec(*arg):
 3         if len(arg) == 0:
 4             return 0
 5         for val in arg:
 6             if not isinstance(val, int):
 7                 return 0
 8         return func(*arg)
 9     return in_dec
10 
11 @dec
12 def my_sum(*arg):
13     return sum(arg)
14 
15 @dec
16 def my_average(*arg):
17     return sum(arg) / len(arg)
18 
19 print (my_sum(1,2,3,4,5,6)) (等同於mysum = dec(my_sum); mysum(1,2,3,4,5,6))
20 print (my_average(1,2,3,4,5,6)) 

咱們來分析一下整個的調用過程:作用域

首先當遇到語法糖@dec時,調用dec,而後它會返回in_dec,因爲my_sum做爲一個參數傳入dec,所以它做爲閉包內的變量被in_dec所使用,這時my_sum被從新賦值my_sum = in_dec,因此咱們調用my_sum時實際上是調用了in_dec,而in_dec有調用了原來的my_sum。以上就是裝飾器所作的事情,其實就是Python閉包的一種應用。class

使用裝飾器的好處在於:一、使代碼能夠複用。從上邊的代碼能夠看出,裝飾器的主要做用是對參數進行檢驗,所以該裝飾器能夠用於全部有相似參數檢驗需求的函數,避免了大量冗餘代碼;二、因爲裝飾器是顯式的,它們在全部須要它們的被調用函數中使用。所以這對於可讀性頗有價值,從而使調試也更加方便。當一個裝飾器編寫的足夠好時,它們是模塊化且清晰明確的。

相關文章
相關標籤/搜索