1. 程式人生 > >Python - 裝飾器 & 閉包(針對初學者)

Python - 裝飾器 & 閉包(針對初學者)

閉包 附加 代碼 位置 定義 class str 分享圖片 參數

一、裝飾器

  本身就是函數,都是用def語法來定義的,為其他函數添加附加功能。

二、應用場景

  假設目前編寫的函數已經上線運行了,某一天,產品有個需求,要在這個裏面新增一個功能,那怎麽去做這個事?最簡單的就是:重新編碼。但是問題是程序已經運行了,修改程序源碼,會有風險發生。

  所以說,我要新增一個功能,不能夠修改函數的源代碼,且不改變原函數的調用方式,這個時候裝飾器就出現了

閉包

  要了解裝飾器首先要知道什麽是閉包

  總結起來就是:

    1、外層函數返回了內存函數的引用

    2、內層函數引用了外層函數的參數

1  def out(num):  #外層函數
2 print(‘1‘)
3 def inner(): #內層函數
4 print(num)
5 print(‘5‘)
6 print(‘2‘)
7 return inner #返回了內層函數的引用
8
9 res = out(4)
10 res()

  這就是閉包,那麽閉包是怎麽執行的呢

1
2
4
5

 當調用out() 的時候,此時執行外層函數,輸出1,輸出2 ,註意:當程序執行到第3行時,只是在此聲明了一個函數,並沒有做任何事情,此時res接收了out的返回值(inner函數的引用)

 當調用res() 的時候,此時相當於調用inner函數,輸出4,輸出5,執行完畢

 執行內部函數的時候,外層函數的變量並沒有被銷毀,可以一直被調用。

def out(num):
    print(1)
    def inner(num_inner):
        print(num)
        print(num_inner)
    print(2)
    return inner

res = out(4)
res(11)
res(22)
res(33)
res(44)

  此時輸出結果為

1
2
4
11
4
22
4
33
4
44

  此種應用,雖然編寫函數的時候會稍微麻煩點,但是可以反復調用,不會被釋放,傳參數的時候也可以簡化

  

裝飾器

  1、只是在原來的函數基礎上增加新的函數,達到在執行原來的函數之前或者之後執行新添加的功能

  2、不改變原函數的調用方式,原來調用哪個函數現在還調用哪個函數

示例一:

def out1(func):    #此函數相當於拓展函數
    print(外層開始執行)
    def inner1():
        print(內層開始執行)
        func()
    print(外層執行完畢)
    return inner1

@out1
def ma():       #此函數相當於原來的函數 print(這是一個主函數) ma()           #調用方式依舊是原來的調用

輸出結果

外層開始執行
外層執行完畢
內層開始執行
這是一個主函數

示例二:

def out1(canshu):
    print(外層開始執行)
    def inner1():
        print(內層開始執行)
        canshu()
    print(外層執行完畢)
    return inner1

# @out1
def ma():
    print(這是一個主函數)
ma = out1(ma)
ma()

輸出結果

外層開始執行
外層執行完畢
內層開始執行
這是一個主函數

可以看到上面兩種方式實現了同樣的功能(示例一屬於閉包函數裝飾了原來的函數)

可以看出

ma = out1(ma)
ma()

只是被 語法糖 @out1 替換掉了

在函數ma上面加上了@out1,就相當於 out1(ma)

當程序執行到@定義的位置,就會自動執行閉包體的外層函數,當執行到原函數調用時,會自動執行閉包體的內層函數

下面附上詳細圖片

技術分享圖片

  

Python - 裝飾器 & 閉包(針對初學者)