Python3 裝飾器解析

測試工匠麻辣燙發表於2020-07-18

第6章 函式

  • 6.1 函式的定義和呼叫
  • 6.2 引數傳遞
  • 6.3 函式返回值
  • 6.4 變數作用域
  • 6.5 匿名函式(lambda)
  • 6.6 遞迴函式
  • 6.7 迭代器
  • 6.8 生成器
  • 6.9 裝飾器

6.9 裝飾器

裝飾器本質上是一個 Python 函式或類,它可以讓其他函式或類在不需要做任何程式碼修改的前提下增加額外功能,它也不會改變函式或類的呼叫方式。

它經常用於有切面需求的場景,比如:插入日誌、效能測試、事務處理、快取、許可權校驗等場景,裝飾器是解決這類問題的絕佳設計。有了裝飾器,我們就可以抽離出大量與函式功能本身無關的雷同程式碼到裝飾器中並繼續重用。

概括的講,裝飾器的作用就是為已經存在的物件新增額外的功能。

裝飾器的語法是將@裝飾器名,放在被裝飾物件上面。

有兩類裝飾器:函式裝飾器、類裝飾器

# 函式裝飾器的語法
@dec
def func():
    pass
引數說明:
@稱為語法糖
dec:裝飾器名字
func:被裝飾的函式名

在介紹裝飾器之前,先明確幾個概念及原則:

原則:

Python程式是從上往下順序執行的,而且碰到函式的定義程式碼塊是不會立即執行的,只有等到該函式被呼叫時,才會執行其內部的程式碼塊。

如果一個函式定義了兩次,那麼後面定義的會覆蓋前面的定義。

在Python中程式碼的放置位置是有區別的,不能隨意擺放,通常函式體要放在呼叫的語句之前。

概念:

函式名、函式體、返回值,函式的記憶體地址、函式名加括號、函式名被當作引數、函式名加括號被當作引數、返回函式名、返回函式名加括號。

# 加操作:無引數
import time


def timer(func):
    def inner():
        t1 = time.time()
        func()
        t2 = time.time()
        return t2 - t1

    return inner


@timer
def add():
    a = 1
    b = 1
    time.sleep(1)
    c = a + b
    print(c)
    return c


add = add()
print(add)

函式名: timeraddinner

函式體:除def那一行外的部分

返回值: return後面的表示式

函式的記憶體地址:id(add)id(outer)等等

函式名加括號:對函式進行呼叫,比如add()timer(func)

函式名作為引數: timer(func)中的func本身是個函式,但作為引數被傳遞給了timer函式

函式名加括號被當做引數:其實就是先呼叫函式,再將它的返回值當做別的函式的引數,例如timer(add())

返回函式名:return inner

返回函式名加括號:return inner(),其實就是先執行inner函式,再將其返回值作為別的函式的返回值。

一個裝飾器例子:

'''
1、@timer,稱為語法糖,其作用是將被裝飾函式add的函式名作為實參傳給裝飾器timer函式的形參func,傳函式名實際傳的是記憶體指向;
2、函式timer內又巢狀了inner函式,返回值是函式名inner,必須要明確的是,傳進去函式名add,返回來inner函式名,結果就是add和inner共同指向在記憶體中定義inner的起始地址,而此時形參func指向在記憶體定義add的起始地址,可在除錯程式過程中通過id方法列印檢視add和inner所指向的記憶體地址的變化情況。
明確這兩點,裝飾器就不難理解了。
'''
# 加操作:無引數
import time


def timer(func):
    def inner():
        t1 = time.time()
        func()
        t2 = time.time()
        return t2 - t1

    return inner


@timer
def add():
    a = 1
    b = 1
    time.sleep(1)
    c = a + b
    print(c)
    return c


add = add()
print(add)
# 加操作:位置引數
import time


def timer(func):
    def inner(a, b):
        t1 = time.time()
        func(a, b)
        t2 = time.time()
        return t2 - t1

    return inner


@timer
def add(a, b):
    # a = 1
    # b = 1
    time.sleep(1)
    c = a + b
    print(c)
    return c


add = add(1, 1)
print(add)
# 加操作:可變引數
import time


def timer(func):
    def inner(*args):
        t1 = time.time()
        func(*args)
        t2 = time.time()
        return t2 - t1

    return inner


@timer
def add(a, b):
    # a = 1
    # b = 1
    time.sleep(1)
    c = a + b
    print(c)
    return c


add = add(1, 1)
print(add)
# 加減乘除操作:可變引數
import time


def timer(func):
    def inner(*args):
        t1 = time.time()
        func(*args)
        t2 = time.time()
        return t2 - t1

    return inner


@timer
def add(a, b):
    # a = 1
    # b = 1
    time.sleep(1)
    c = a + b
    print(c)
    return c


@timer
def plus(a, b):
    # a = 1
    # b = 1
    time.sleep(2)
    c = a - b
    print(c)
    return c


@timer
def multi(a, b):
    # a = 1
    # b = 1
    time.sleep(3)
    c = a * b
    print(c)
    return c


@timer
def div(a, b):
    # a = 1
    # b = 1
    time.sleep(4)
    c = a / b
    print(c)
    return c


add = add(1, 1)
print(add)
plus = plus(2, 1)
print(plus)
multi = multi(3, 1)
print(multi)
div = div(4, 1)
print(div)

敬請關注個人微信公眾號:測試工匠麻辣燙

相關文章