人妖在线一区,国产日韩欧美一区二区综合在线,国产啪精品视频网站免费,欧美内射深插日本少妇

新聞動態(tài)

python三大器之裝飾器詳解

發(fā)布日期:2021-12-22 22:40 | 文章來源:源碼之家

裝飾器

講裝飾器之前要先了解兩個概念:

  • 對象引用 :對象名僅僅只是個綁定內(nèi)存地址的變量
def func():# 函數(shù)名僅僅只是個綁定內(nèi)存地址的變量 
	print("i`m running") 
# 這是調(diào)用  
func()  # i`m running
# 這是對象引用,引用的是內(nèi)存地址  
func2 = func  
print(func2 is func)  # True
# 通過引用進(jìn)行調(diào)用  
func2()  # i`m running
  • 閉包:定義一個函數(shù)A,然后在該函數(shù)內(nèi)部再定義一個函數(shù)B,并且B函數(shù)用到了外邊A函數(shù)的變量
    def out_func():
    	out_a = 10
    	def inner_func(inner_x):
    		return out_a + inner_x
    	return inner_func
    out = out_func()
    print(out)  # <function out_func.<locals>.inner_func at 0x7ff378af5c10> out_func返回的是inner_func的內(nèi)存地址
    print(out(inner_x=2))  # 12
    

裝飾器和閉包不同點在于:裝飾器的入?yún)⑹?strong>函數(shù)對象,閉包入?yún)⑹瞧胀〝?shù)據(jù)對象

def decorator_get_function_name(func):
	"""
	獲取正在運行函數(shù)名
	:return:
	"""
	def wrapper(*arg):
		"""
		wrapper
		:param arg:
		:return:
		"""
		print(f"當(dāng)前運行方法名:{func.__name__}  with  params: {arg}")
		return func(*arg)
	return wrapper
@decorator_get_function_name
def test_func_add(x, y):
	print(x + y)
@decorator_get_function_name
def test_func_sub(x, y):
	print(x - y)
test_func_add(1, 2)
# 當(dāng)前運行方法名:test_func_add  with  params: (1, 2)
# 3
test_func_sub(3, 5)
# 當(dāng)前運行方法名:test_func_sub  with  params: (3, 5)
# -2

常用于如鑒權(quán)校驗,例如筆者會用于登陸校驗:

def login_check(func):
 def wrapper(request, *args, **kwargs):
  if not request.session.get('login_status'):
return HttpResponseRedirect('/api/login/')
  return func(request, *args, **kwargs)
 return wrapper
@login_check
def edit_config():
	pass

裝飾器內(nèi)部的執(zhí)行邏輯:

"""
>  1. def login_check(func):  ==>將login_check函數(shù)加載到內(nèi)存
>  ....
>  @login_check  ==>此處已經(jīng)在內(nèi)存中將login_check這個函數(shù)執(zhí)行了!;并不需要等edit_config()實例化調(diào)用
>  2. 上例@login_check內(nèi)部會執(zhí)行以下操作:
>	  2.1 執(zhí)行l(wèi)ogin_check函數(shù),并將 @login_check 下面的 函數(shù)(edit_config) 作為login_check函數(shù)的參數(shù),即:@login_check 等價于 login_check(edit_config)
>  2.2 內(nèi)部就會去執(zhí)行:
def wrapper(*args):
 # 校驗session...
 return func(request, *args, **kwargs)# func是參數(shù),此時 func 等于 edit_config,此處相當(dāng)于edit_config(request, *args, **kwargs)
return wrapper  # 返回的 wrapper,wrapper代表的是函數(shù)對象,非函數(shù)實例化對象
2.3 其實就是將原來的 edit_config 函數(shù)塞進(jìn)另外一個函數(shù)中,另一個函數(shù)當(dāng)中可以做一些操作;再執(zhí)行edit_config
2.4 將執(zhí)行完的 login_check 函數(shù)返回值(也就是 wrapper對象)將此返回值再重新賦值給新 edit_config,即:
2.5 新edit_config = def wrapper:
 # 校驗session...
return 原來edit_config(request, *args, **kwargs) 
>  3. 也就是新edit_config()=login_check(edit_config):wrapper(request, *args, **kwargs):return edit_config(request, *args, **kwargs) 有點繞,大家看步驟細(xì)細(xì)理解。
"""

同樣一個函數(shù)也可以使用多個裝飾器進(jìn)行裝飾,執(zhí)行順序從上到下

from functools import wraps
def w1(func):
	@wraps(func)
	def wrapper(*args, **kwargs):
		print("這里是第一個校驗")
		return func(*args, **kwargs)
	return wrapper
def w2(func):
	@wraps(func)
	def wrapper(*args, **kwargs):
		print("這里是第二個校驗")
		return func(*args, **kwargs)
	return wrapper
def w3(func):
	def wrapper(*args, **kwargs):
		print("這里是第三個校驗")
		return func(*args, **kwargs)
	return wrapper
@w2  # 這里其實是w2(w1(f1))
@w1  # 這里是w1(f1)
def f1():
	print(f"i`m f1, at {f1}")
@w3
def f2():
	print(f"i`m f2, at {f2}")
# ====================== 實例化階段 =====================
f1()
# 這里是第二個校驗
# 這里是第一個校驗
# i`m f1, at <function f1 at 0x7febc52f5e50>
f2()
# 這里是第三個校驗
# i`m f2, at <function w3.<lo

有同學(xué)可能要好奇 為什么f1對象打印的是“<function f1 at 0x7febc52f5e50>”,f2對象打印的是“<function w3..wrapper at 0x7febc52f5f70>”(也就是步驟2.5造成的,賦的值是wrapper對象),這就跟w1和w2 內(nèi)部wrapper使用的wraps裝飾器有關(guān)系了。

wraps的作用是:被修飾的函數(shù)(也就是里面的func)的一些屬性值賦值給修飾器函數(shù)(wrapper)包括元信息和“函數(shù)對象”等。

同時裝飾器也可以接受參數(shù):

def decorator_get_function_duration(enable):
	"""
	:param enable:  是否需要統(tǒng)計函數(shù)執(zhí)行耗時
	:return: 
	"""
	print("this is decorator_get_function_duration")
	def inner(func):
		print('this is inner in decorator_get_function_duration')
		@wraps(func)
		def wrapper(*args, **kwargs):
			print('this is a wrapper in decorator_get_function_duration.inner')
			if enable:
				start = time.time()
				print(f"函數(shù)執(zhí)行前:{start}")
				result = func(*args, **kwargs)
				print('[%s]`s enable was %s it`s duration : %.3f s ' % (func.__name__, enable, time.time() - start))
			else:
				result = func(*args, **kwargs)
			return result
		return wrapper
	return inner
def decorator_1(func):
	print('this is decorator_1')
	@wraps(func)
	def wrapper(*args, **kwargs):
		print('this is a wrapper in decorator_1')
		return func(*args, **kwargs)
	return wrapper
def decorator_2(func):
	print('this is decorator_2')
	@wraps(func)
	def wrapper(*args, **kwargs):
		print('this is a wrapper in decorator_2')
		return func(*args, **kwargs)
	return wrapper
@decorator_1 # 此處相當(dāng):decorator_1(decorator_2(decorator_get_function_duration(enable=True)(fun)))
@decorator_2 # = decorator_2(decorator_get_function_duration(enable=True)(fun))
@decorator_get_function_duration(enable=True)  # = decorator_get_function_duration(enable=True)(fun)
def fun():
	time.sleep(2)
	print("fun 執(zhí)行完了~")
fun()
# ======== enable=False ============
"""
this is decorator_get_function_duration
this is inner in decorator_get_function_duration
this is decorator_2
this is decorator_1
this is a wrapper in decorator_1
this is a wrapper in decorator_2
this is a wrapper in decorator_get_function_duration.inner
fun 執(zhí)行完了~
"""
# ======== enable=True ============
"""
this is decorator_get_function_duration
this is inner in decorator_get_function_duration
this is decorator_2
this is decorator_1
this is a wrapper in decorator_1
this is a wrapper in decorator_2
this is a wrapper in decorator_get_function_duration.inner
函數(shù)執(zhí)行前:1634635708.648994
fun 執(zhí)行完了~
[fun]`s enable was True it`s duration : 2.002 s 
"""

總結(jié)

本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注本站的更多內(nèi)容!

版權(quán)聲明:本站文章來源標(biāo)注為YINGSOO的內(nèi)容版權(quán)均為本站所有,歡迎引用、轉(zhuǎn)載,請保持原文完整并注明來源及原文鏈接。禁止復(fù)制或仿造本網(wǎng)站,禁止在非www.sddonglingsh.com所屬的服務(wù)器上建立鏡像,否則將依法追究法律責(zé)任。本站部分內(nèi)容來源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來,僅供學(xué)習(xí)參考,不代表本站立場,如有內(nèi)容涉嫌侵權(quán),請聯(lián)系alex-e#qq.com處理。

相關(guān)文章

實時開通

自選配置、實時開通

免備案

全球線路精選!

全天候客戶服務(wù)

7x24全年不間斷在線

專屬顧問服務(wù)

1對1客戶咨詢顧問

在線
客服

在線客服:7*24小時在線

客服
熱線

400-630-3752
7*24小時客服服務(wù)熱線

關(guān)注
微信

關(guān)注官方微信
頂部