python筆記24_裝飾器

主要內容:

  • 小目標:理解裝飾器
  • 主要內容:裝飾器基本語法,裝飾器應用

若是看完這篇文章,你仍是弄不明白裝飾器;
你來找我,我保證不打你,我給你發100的大紅包。數據結構

1. 一個案例

1.1 需求:兩個函數

mySum:計算列表的和,參數必須爲列表
myMax:統計列表的最大值,參數必須爲列表閉包

代碼實現:框架

def mySum(args):
    #判斷args是不是列表
    if isinstance(args, list):
        return sum(args)
    return -1

def myMax(args):
    #判斷args是不是列表
    if isinstance(args, list):
        return max(args)
    return -1
print(mySum([1,2,3]))
print(mySum((1,2,3)))
print(myMax(123))

結果:6, -1, -1ide

1.2 新需求:參數可使元組

修改代碼:函數

def mySum(args):
    #判斷args是不是列表
    if isinstance(args, (list, tuple)):
        return sum(args)
    return -1

def myMax(args):
    #判斷args是不是列表
    if isinstance(args, (list, tuple)):
        return max(args)
    return -1
print(mySum([1,2,3]))
print(mySum((1,2,3)))
print(myMax(123))

結果:6,6,-1code

1.3 問題:

  • 若是增長其餘數據結構如何處理?
  • 若是有N個這樣函數如何處理?

從上一步修改中能夠看到,判斷條件時相同的,惟一不一樣時處理方式。作用域

2. 閉包的應用

對上面進行分析,解決方式:get

每一個函數的核心功能不一樣,可是判斷條件相同
將相同部分拆分紅函數,使用閉包處理下:it

def decoFunc(func):
    #checkArgs爲內置函數,func對於checkArgs是外部變量
    def checkArgs(args):
        #統一處理參數
        if isinstance(args, (list, tuple)):
            return func(args)
        return -1
    return checkArgs

#自定義的sun函數
mySum = decoFunc(sum)
#自定義max函數
myMax = decoFunc(max)
print(mySum([1,2,3]))
print(mySum((1,2,3)))
print(myMax(123))

結果:6,6,-1io

  • 分析:

    decoFunc(func)中的func對於checkArgs爲外部變量
    decoFunc返回值爲checkArgs函數
    mySum, myMax指向checkArgs函數,可是每一個函數內部的func不一樣
    mySum, myMax調用以後,檢查args,而後使用不一樣func處理ars
    你們能夠吧這個過程理解下,而後咱們來看裝飾器

3.裝飾器

如何理裝飾器:

裝飾器:修改函數並返回新的函數;
裝飾器與閉包原理相似,可是隻用來處理函數;

基本語法:

@deco
def func(args):
    pass

來看例子

def decoFunc(func):
    #checkArgs爲內置函數,func對於checkArgs是外部變量
    def checkArgs(args):
        #統一處理參數
        if isinstance(args, (list, tuple)):
            return func(args)
        return -1
    print('checkArgs:', checkArgs)
    return checkArgs

@decoFunc
def mySum(args):
    return sum(args)
print('mySum:', mySum)

結果:

checkArgs: <function decoFunc.<locals>.checkArgs at 0x000001C4A21580D8>
mySum: <function decoFunc.<locals>.checkArgs at 0x000001C4A21580D8>

分析:

mySum變量名指向decoFunc中的返回值:checkArgs函數br/>@decoFunc就是裝飾器的語法糖
從結果中看到,咱們沒有調用mySum函數,可是裝飾器函數會默認執行

裝飾器實質:對比兩個例子,裝飾器實質:mySum = decoFunc(mySum)

3.帶參數的裝飾器

新需求:在不修改checkArgs參數前提下,調用mySum,myMax前打印相應的函數名

直接上代碼:

def decoFunc(fname):
    print("call decoFunc")
    #在_decoFunc在加一層函數,返回_decoFunc
    def _decoFunc(func):
        #checkArgs爲內置函數,func對於checkArgs是外部變量
        def checkArgs(args):
            #統一處理參數
            if isinstance(args, (list, tuple)):
                print("call func:", fname)
                return func(args)
            return -1
        print('checkArgs:', checkArgs)
        return checkArgs
    return _decoFunc

@decoFunc('mySum')
def mySum(args):
    return sum(args)
print('mySum:', mySum)
mySum([1,2,3,4,5])

結果:

call decoFunc
checkArgs: <function decoFunc.<locals>._decoFunc.<locals>.checkArgs at 0x000001C4A1D00B88>
mySum: <function decoFunc.<locals>._decoFunc.<locals>.checkArgs at 0x000001C4A1D00B88>
call func: mySum

分析:
函數包含關係:decoFunc->_decoFunc->checkArgs
@decoFunc('mySum')執行過程:

1.執行decoFunc('mySum'),設置fname,返回_decoFuncbr/>2.執行@decoFunc('mySum')實質是@返回_decoFunc,
3>mysum = _decoFunc(mySum)

你們看到裝飾器,尤爲帶參數的裝飾器,感受暈暈的,
咱們要作的,就是一步一步分析,搞清楚原理;
以上就是裝飾相關內容;

總結:

  • 理解裝飾器,必須先理解閉包;
  • 理解閉包,必須弄清楚做用域及函數返回值;
  • 裝飾器在實際工做,尤爲適用第三方框架時候(Djano,Scrapy等),應用十分普遍
相關文章
相關標籤/搜索