Python基礎 裝飾器

2021-09-11 01:43:51 字數 4309 閱讀 3507

裝飾器是程式開發中經常會用到的乙個功能,程式開發的基礎知識,用好了裝飾器,開發效率如虎添翼,所以這也是python面試中必問的問題,但對於好多初次接觸這個知識的人來講,這個功能有點繞,這個都不會,別跟人家說你會python, 看了下面的文章,保證你學會裝飾器。

裝飾器(decorator):首先我們需要知道裝飾器本身就是乙個函式,而這個函式存在的意義就是為其他函式新增附加功能的。

而從某種程度上來說:裝飾器並非乙個功能特性,它只是乙個語法糖,因為從本質上來講:它實現的是將乙個函式或者物件作為引數傳遞給另外乙個函式或者物件,最後再返回新的函式物件,而這個新的函式或者物件內部既實現了原函式的功能,也為其附加了新的功能。

在實現目的-->為其他函式新增附加功能(比如在驗證功能基礎上新增乙個人臉識別),在這個前提下還需要遵循兩個原則,即:

①、不修改被修飾函式的源**。

② 、不修改被修飾函式的呼叫方式。

引入日誌

函式執行時間統計

執行函式前預備處理

執行函式後清理功能

許可權校驗等場景

快取先舉個例子:在兩開花前新增乙個驗證功能

def test0():

print("兩開花")

test()

寫**要遵循開放封閉原則,雖然在這個原則是用的物件導向開發,但是也適用於函式式程式設計,簡單來說,它規定已經實現的功能**不允許被修改,但可以被擴充套件,即:

下面是最原始的改法:

def test0():

print("兩開花")

def deco(func):

def warpper():

print("驗證")

func()

return warpper

test=deco(test0)

test()

那麼使用裝飾器會是怎麼樣呢?

def deco(func):

def warpper():

print("驗證")

func()

return warpper

#被修飾函式

@deco #@deco <==> test =deco(test)

def test():

print("兩開花")

test()

以上面例子來講解裝飾器的實現原理

python直譯器從上往下解釋**。步驟如下:

1.將deco載入到記憶體裡

2.@deco

沒錯, 從表面上看直譯器僅僅會解釋這兩句**,因為函式在 沒有被呼叫之前其內部**不會被執行。

從表面上看直譯器著實會執行這兩句,但是 @deco 這一句**裡卻有大文章, @函式名 是python的一種語法糖。

@deco <<====>>test = deco(test)

@deco內部執行的操作有:

1.執行deco函式,並將@下面的函式作為deco函式的引數,等價於deco(test)

2.將deco(test)的返回值賦值給@下面的函式名test,即test = deco(test)

如此一來,即保證了原功能函式不變,又能給原功能新增新的功能,而且呼叫方式保持不變,是不是很有用。

1.無引數的函式

def deco1(func):

def warpper():

func()

print(" 修飾函式")

return warpper

#被修飾函式

@deco1 #@deco <==> test =deco1(test)

def test():

print("test--被修飾函式")

test()

上面**理解裝飾器執行行為可理解成

test = deco1(test)

test先作為deco1函式引數賦值給func,test指向deco1的返回值warpper

test()

#內部函式warpper引用,所以外部func還未釋放,func儲存著原始的test

2.被裝飾的函式有引數

def deco2(func):

def warpper(name):

func(name)

print(" 修飾函式")

return warpper

#被修飾函式

@deco2 #@deco <==> test =deco1(test)

def test2(name):

print("test--被修飾函式"+name)

test2("lian")

3.被裝飾的函式有不定長引數

def deco2(func):

print("hh")

def warpper(*args,**kwargs):

func(*args, **kwargs)

print(" 修飾函式")

return warpper

#被修飾函式

@deco2

def test2(*args, **kwargs):

print("test--被修飾函式",args)

test2(1,2,3,4)

test2(2,3)

4.裝飾器中的return

def deco2(func):

def warpper(name):

ret=func(name)

print(" 修飾函式")

return ret

return warpper

#被修飾函式

@deco2

def test2(name):

print("test--被修飾函式"+name)

return "兩開花"

test2("lian")

5.裝飾器帶引數,在原有裝飾器的基礎上,設定外部變數

def deco3(max):

def deco3(func):

def warpper():

for i in range(max):

func()

print(" 修飾函式")

return warpper

return deco3

# 下面的裝飾過程

# 1. 呼叫deco3(max)

# 2. 將步驟1得到的返回值,即deco3返回, 然後deco3(test)

#綜述:test() = (deco3(2))(test)()

#被修飾函式

@deco3(2)

def test3():

print("test--被修飾函式")

test3()

6.多個裝飾器對同乙個函式進行裝飾

def a1(func):

def b1():

print("執行a1-b1")

func()

return b1

def a2(func):

def b2():

print('執行a2-b2')

func()

return b2

@a1@a2

def test3():

print("test--被修飾函式")

test3() #====>a1((a2(test3)))()

7.類裝飾器

裝飾器函式其實是這樣乙個介面約束,它必須接受乙個callable物件作為引數,然後返回乙個callable物件。在python中一般callable物件都是函式,但也有例外。只要某個物件重寫了__call__()方法,那麼這個物件就是callable的。

class foo(object): 

def __init__(self,func):

self.func=func

def __call__(self):

print("執行call")

self.func()

@foo

def foo():

print('foo')

foo()

今天就講到這裡了!

python基礎 裝飾器

裝飾器本質就是函式,功能是為其他函式新增附加功能。原則 不修改被修飾函式的源 不修改被修飾函式的呼叫方式 裝飾器的知識儲備 裝飾器 高階函式 函式巢狀 閉包 import time 定義乙個裝飾器計算函式執行時間 def timer func start time time.time res fun...

python基礎 裝飾器

裝飾器形成的過程 最簡單的裝飾器 有返回值的 有乙個引數 萬能引數 裝飾器的作用 原則 開放封閉原則 語法糖 裝飾器的固定模式 import time print time.time 獲取當前時間 time.sleep 10 讓程式在執行到這個位置的時候停一會兒 def timmer f 裝飾器函式...

python基礎 裝飾器

一 裝飾器定義 器即函式 裝飾即修飾,意指為其他函式新增新功能 裝飾器定義 本質就是函式,功能是為其他函式新增新功能 二 裝飾器需遵循的原則 1.不修改被裝飾函式的源 開放封閉原則 2.為被裝飾函式新增新功能後,不修改被修飾函式的呼叫方式 三 實現裝飾器知識儲備 裝飾器 高階函式 函式巢狀 閉包 四...