分解裝飾器(語法糖)

2021-08-16 17:22:23 字數 4421 閱讀 9221

一、裝飾器的定義:通俗地說,就是裝飾其他函式,為其他函式新增附加功能,本質上也是函式。

但要遵循兩個原則:

1.不能修改被裝飾函式的源**

2.不能修改被裝飾函式的呼叫方式

簡言之,裝飾器對被裝飾函式是完全透明的。

二、在實現裝飾器之前,我們還要先弄明白以下3個知識點:

1.函式即「變數」:在python中,無論是變數還是函式,在定義後,python都會在記憶體中為其分配乙個位址,用來存放變數或函式的內容,在呼叫該變數或函式時,只要能在記憶體中找到變數或函式的記憶體位址,就可以正常執行。

舉例來說,

def

foo():

print('in the foo')

bar()

foo() # 如果在此刻呼叫函式foo,就會報錯,因為函式bar還沒有定義,記憶體中找不到其內容

defbar

(): print('in the bar')

foo() # 而在此刻呼叫函式foo,就可以正常執行,因為呼叫前,函式bar已正常定義及分配記憶體位址

2.高階函式

1) 把乙個函式名做為實參傳遞給另乙個函式

(實現在不修改被裝飾函式源**的情況下為其新增附加功能)

舉例說明,

import time

defdeco

(func):

start_time = time.time()

func()

stop_time = time.time()

deftest1

(): time.sleep(3)

print('in the test1')

deco(test1) # 在不修改test1源**的情況下,實現了計算函式test1的執行時間

2) 返回值中包含函式名

(實現了不修改被裝飾函式的呼叫方式)

import time

deffoo

(func):

print(func) # 列印的是函式func的記憶體位址

return func

defbar

(): time.sleep(3)

print('in the bar')

bar = foo(bar)

bar() # 顯然,呼叫方式沒有被改變

3.巢狀函式:在乙個函式裡再定義另乙個函式

def

gradpa

(): x=1

defdad

(): x=2

defson

(): x=3

print(x)

son()

dad()

gradpa()

輸出結果:3

注意:巢狀函式必須是在函式裡再定義另乙個函式,而高階函式是呼叫另乙個函式

三、裝飾器的實現:高階函式+巢狀函式

被裝飾函式沒有引數

import time

# 裝飾器timer

deftimer

(func):

defdeco

(): start_time = time.time()

func()

stop_time = time.time()

print('the function run time is %s' %(stop_time - start_time))

return deco

@timer # 在python裡,用@+裝飾器函式名,放在被裝飾函式上面,實際等同於test1 = timer(test1)

deftest1

(): time.sleep(3)

print('in the test1')

# test1 = timer(test1) # 結果為deco

test1() #等同於deco()

2.被裝飾函式有0-n個引數

*args:不固定位置引數

**kwargs:關鍵字引數

import time

# 裝飾器timer

deftimer

(func):

# 加入*args, **kwargs,無論被裝飾函式擁有幾個引數,都可以正常執行

defdeco

(*args, **kwargs):

start_time = time.time()

func(*args, **kwargs)

stop_time = time.time()

print('the function run time is %s' %(stop_time - start_time))

return deco

@timer

deftest2

(name):

time.sleep(3)

print('in the test2',name)

# test2 = timer(test2) # 結果為deco

test2('amy') #等同於deco('amy')

3.被裝飾函式有返回值

import time

# 裝飾器timer

deftimer

(func):

defdeco

(*args, **kwargs):

start_time = time.time()

res = func(*args, **kwargs) # 將函式func的返回值賦給res

stop_time = time.time()

print('the function run time is %s' %(stop_time - start_time))

return res # 返回res,就可以將被裝飾函式的返回值輸出

return deco

@timer

deftest3

(name):

time.sleep(3)

print('in the test3',name)

return

'hello test3'

# test3 = timer(test3) # 結果為deco

test3('amy') #等同於deco('amy')

4.根據條件給被裝飾函式裝飾不同功能

舉例說明:假設有三個頁面,index首頁無需登入就能訪問,home和bbs頁面需要輸入正確使用者名稱密碼才能進入,且home用本地認證,bbs用遠端ldap驗證

user = 'amy'

passwd = 'abc123'

# 使用者登入認證裝飾器

defauth

(auth_type):

# 第一層,傳入不同的驗證方式auth_type,返回函式loggin

defloggin

(func):

# 第二層,傳入被裝飾函式func,返回函式deco

defdeco

(*args, **kwargs):

if auth_type == 'local':

username = input('username:').strip()

password = input('password:').strip()

if username == user and password == passwd:

res = func(*args, **kwargs)

return res

else:

exit('invalid username or password!')

elif auth_type == 'ldap':

print('sorry, i don\'t konw ldap')

return deco

return loggin

defindex

(): print('welcome to index page')

@auth(auth_type='local') # 執行結果等同於home = deco()

defhome

(): print('welcome to home page')

@auth(auth_type='ldap')

defbbs

(): print('welcome to bbs page')

index()

home()

bbs()

裝飾器語法糖

什麼是裝飾器語法糖 toc裝飾器語法糖屬於裝飾器的 注意 在使用裝飾器語法糖時,裝飾器必須定義在被裝飾物件之上 import time 統計函式執行時間裝飾器 def inner args,kwargs 被裝飾物件的引數 呼叫前增加新功能 start time time.time 呼叫被裝飾物件,並...

Python語法糖 裝飾器

這裡用來記錄python各種甜得發膩的語法糖,以及各種變形用法。太初,神諭 pythonic import light,於是有了光。裝飾器是用來給函式增加新功能的,對於支援高階函式的語言,函式引數直接穿進去就好了。但是python提供了更為優雅的解決方案,只需要乙個 就能搞定。裝飾器函式需要單獨寫出...

Python語法糖 裝飾器

這裡用來記錄python各種甜得發膩的語法糖,以及各種變形用法。太初,神諭 pythonic import light,於是有了光。裝飾器是用來給函式增加新功能的,對於支援高階函式的語言,函式引數直接穿進去就好了。但是python提供了更為優雅的解決方案,只需要乙個 就能搞定。裝飾器函式需要單獨寫出...