1. 程式人生 > >我要學python之裝飾器

我要學python之裝飾器

fun 重新 特殊 int 接口調用 返回 一個 python裝飾器 最簡

python裝飾器

python裝飾器就是用於拓展原來函數功能的一種函數,這個函數的特殊之處在於它的返回值也是一個函數,使用python裝飾器的好處就是在不用更改原函數的代碼前提下給函數增加新的功能。

一般而言,我們要想拓展原來函數代碼,最直接的辦法就是侵入代碼裏面修改,但是最簡單的方式並不是最安全最合適的方式,根據擴展開放修改封閉的原則,修改原函數代碼是不可取的.比如下面的有一個案例:

A公司有一個核心接口部門M提供核心業務接口,有三個業務部門(N,W,Z)需要調用核心業務接口,在正常運行了一年後,公司規範接口調用需要驗證用戶權限進行接口調用,現在需要實現這個擴展功能如何在花費最小成本完成?

樣例代碼如下:

############### 核心接口部門 ###############

def f1():
    print(‘f1‘)

def f2():
    print(‘f2‘)

def f3():
    print(‘f3‘)

def f4():
    print(‘f4‘)

############### 業務部門N 調用核心接口提供的功能 ###############

f1()
f2()
f3()
f4()

############### 業務部門W 調用核心接口提供的功能 ###############

f1()
f2()
f3()
f4()

############### 業務部門Z 調用核心接口提供的功能 ###############

f1()
f2()
f3()
f4()

.核心接口部門重構原函數,添加驗證代碼

############### 核心接口部門 ###############
def verify():
    print(‘驗證代碼‘)

def f1():
   verify()
    print(‘f1‘)

def f2():
    verify()
    print(‘f2‘)

def f3():
    verify()
    print(‘f3‘)

def f4():
   verify()
    print(‘f4‘)

分析:違反了開放封閉原則!對擴展是開放的,對修改封閉。對於核心的功能寫好之後是不應許進入到功能裏面去修改的。如果有1000個接口,你就得改一千次,雖然對於調用者無感,但核心接口部門成本很高。

核心接口部門擴展驗證接口,業務部門調用時驗證

############### 核心接口部門 ###############
def verify():
    print(‘驗證代碼‘)

def f1():
    print(‘f1‘)

def f2():
    print(‘f2‘)

def f3():
    print(‘f3‘)

def f4():
    print(‘f4‘)

############### 業務部門N 調用核心接口提供的功能 ###############
if(verify()){
f1()
f2()
f3()
f4()
} else {
    print(‘未通過驗證‘)
}

############### 業務部門W 調用核心接口提供的功能 ###############
if(verify()){
f1()
f2()
f3()
f4()
} else {
    print(‘未通過驗證‘)
}

############### 業務部門Z 調用核心接口提供的功能 ###############
if(verify()){
f1()
f2()
f3()
f4()
} else {
    print(‘未通過驗證‘)
}

分析:
上述代碼滿足開放封閉原則。核心接口部門也是只要擴展一個驗證功能即可,但業務調用部門需要進行驗證功能調用,這不利於調用者使用。

核心接口裝飾器進行驗證,業務部門無感

############### 核心接口部門 ###############

def verify(func):
    def inner():
        # 驗證1
        # 驗證2
        # 驗證3
        return func()
    return inner

@verify
def f1():
    print(‘f1‘)
@verify
def f2():
    print(‘f2‘)
@verify
def f3():
    print(‘f3‘)
@verify
def f4():
    print(‘f4‘)

分析:

上述裝飾器解決驗證問題,只要核心接口部門進行操作,並且滿足開放封閉原則。下面以f1為例,
執行verify函數,並將 @verify 下面的 函數 作為verify函數的參數,即:@verify 等價於verify(f1)
所以,內部就會去執行:
def inner:
    #驗證
    return f1()   # func是參數,此時 func 等於 f1
return inner     # 返回的 inner,inner代表的是函數,非執行函數
    其實就是將原來的 f1 函數塞進另外一個函數中
    將執行完的 verify 函數返回值賦值給@verify下面的函數的函數名
    verify函數的返回值是:
    def inner:
    #驗證
    return 原來f1()  # 此處的 f1 表示原來的f1函數
            然後,將此返回值再重新賦值給 f1,即:
            新f1 = def inner:
                        #驗證
                        return 原來f1() 
    所以,以後業務部門想要執行 f1 函數時,就會執行 新f1 函數,
    在 新f1 函數內部先執行驗證,再執行原來的f1函數,然後將 原來f1 函數的返回值 返回給了業務調用者。
    如此一來, 即執行了驗證的功能,又執行了原來f1函數的內容,並將原f1函數返回值 返回給業務調用著。

擴展

上面我們寫的是沒有帶參數的,我們如何寫帶參數的呢?

帶一個參數

def verify(func):
    def inner(arg1):
        # 驗證1
        # 驗證2
        # 驗證3
        return func(arg1)
    return inner
@verify
def f1(arg1):
    print(‘f1‘)

備註:如果你要指定參數個數,就添加指定個數參數到裏面即可。如下:

帶兩個參數

def verify(func):
    def inner(arg1,arg2):
        # 驗證1
        # 驗證2
        # 驗證3
        return func(arg1,arg2)
    return inner

@verify
def f1(arg1,arg2):
    print(‘f1‘)

帶N個參數

def verify(func):
    def inner(*args,**kwargs):
        # 驗證1
        # 驗證2
        # 驗證3
        return func(*args,**kwargs)
    return inner

@verify
def f1(arg1,arg2,arg3,arg4,arg5):
    print(‘f1‘)

一個函數可以有多個裝飾器

def w1(func):
    def inner(*args,**kwargs):
        # 驗證1
        # 驗證2
        # 驗證3
        return func(*args,**kwargs)
    return inner

def w2(func):
    def inner(*args,**kwargs):
        # 驗證1
        # 驗證2
        # 驗證3
        return func(*args,**kwargs)
    return inner

@w1
@w2
def f1(arg1,arg2,arg3):
    print ‘f1‘

我要學python之裝飾器