欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

python三大器之裝飾器詳解

 更新時間:2021年10月20日 10:17:29   投稿:BJT  
這篇文章主要介紹了Python中的裝飾器,涉及到Python中很多重要的特性,小編覺得這篇文章寫的還不錯,需要的朋友可以參考下

裝飾器

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

  • 對象引用 :對象名僅僅只是個綁定內(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
    

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

def decorator_get_function_name(func):
	"""
	獲取正在運(yùn)行函數(shù)名
	:return:
	"""
	def wrapper(*arg):
		"""
		wrapper
		:param arg:
		:return:
		"""
		print(f"當(dāng)前運(yùn)行方法名:{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)前運(yùn)行方法名:test_func_add  with  params: (1, 2)
# 3
test_func_sub(3, 5)
# 當(dāng)前運(yùn)行方法名:test_func_sub  with  params: (3, 5)
# -2

常用于如鑒權(quán)校驗(yàn),例如筆者會用于登陸校驗(yà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()實(shí)例化調(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):
          # 校驗(yàn)session...
          return func(request, *args, **kwargs)   # func是參數(shù),此時 func 等于 edit_config,此處相當(dāng)于edit_config(request, *args, **kwargs)
      return wrapper     # 返回的 wrapper,wrapper代表的是函數(shù)對象,非函數(shù)實(shí)例化對象
      2.3 其實(shí)就是將原來的 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:
             # 校驗(yàn)session...
            return 原來edit_config(request, *args, **kwargs) 
>  3. 也就是新edit_config()=login_check(edit_config):wrapper(request, *args, **kwargs):return edit_config(request, *args, **kwargs) 有點(diǎn)繞,大家看步驟細(xì)細(xì)理解。
"""

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

from functools import wraps
def w1(func):
	@wraps(func)
	def wrapper(*args, **kwargs):
		print("這里是第一個校驗(yàn)")
		return func(*args, **kwargs)
	return wrapper

def w2(func):
	@wraps(func)
	def wrapper(*args, **kwargs):
		print("這里是第二個校驗(yàn)")
		return func(*args, **kwargs)
	return wrapper

def w3(func):
	def wrapper(*args, **kwargs):
		print("這里是第三個校驗(yàn)")
		return func(*args, **kwargs)
	return wrapper

@w2  # 這里其實(shí)是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}")
# ====================== 實(shí)例化階段 =====================
f1()
# 這里是第二個校驗(yàn)
# 這里是第一個校驗(yàn)
# i`m f1, at <function f1 at 0x7febc52f5e50>
f2()
# 這里是第三個校驗(yàn)
# 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)容!

相關(guān)文章

  • django foreignkey(外鍵)的實(shí)現(xiàn)

    django foreignkey(外鍵)的實(shí)現(xiàn)

    這篇文章主要介紹了django foreignkey(外鍵)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07
  • python中棧的原理及實(shí)現(xiàn)方法示例

    python中棧的原理及實(shí)現(xiàn)方法示例

    這篇文章主要介紹了python中棧的原理及實(shí)現(xiàn)方法,結(jié)合實(shí)例形式分析了Python棧的概念、原理、常見操作方法及相關(guān)使用技巧,需要的朋友可以參考下
    2019-11-11
  • Python中Qslider控件實(shí)操詳解

    Python中Qslider控件實(shí)操詳解

    在本篇文章里小編給大家整理的是一篇關(guān)于Python中Qslider控件實(shí)操詳解內(nèi)容,對此有興趣的朋友們可以跟著學(xué)習(xí)參考下。
    2021-02-02
  • python實(shí)現(xiàn)plt x軸坐標(biāo)按1刻度顯示

    python實(shí)現(xiàn)plt x軸坐標(biāo)按1刻度顯示

    這篇文章主要介紹了python實(shí)現(xiàn)plt x軸坐標(biāo)按1刻度顯示,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • 對python中的argv和argc使用詳解

    對python中的argv和argc使用詳解

    今天小編就為大家分享一篇對python中的argv和argc使用詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-12-12
  • python如何在文件中部插入信息

    python如何在文件中部插入信息

    這篇文章主要介紹了python如何在文件中部插入信息問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • 在終端啟動Python時報錯的解決方案

    在終端啟動Python時報錯的解決方案

    這篇文章主要介紹了在終端啟動Python時報錯的解決方案,幫助大家更好的理解和使用python,感興趣的朋友可以了解下
    2020-11-11
  • Python多進(jìn)程通信Queue、Pipe、Value、Array實(shí)例

    Python多進(jìn)程通信Queue、Pipe、Value、Array實(shí)例

    這篇文章主要介紹了Python多進(jìn)程通信Queue、Pipe、Value、Array實(shí)例,queue和pipe用來在進(jìn)程間傳遞消息、Value + Array 是python中共享內(nèi)存映射文件的方法,需要的朋友可以參考下
    2014-11-11
  • python小練習(xí)之爬魷魚游戲的評價生成詞云

    python小練習(xí)之爬魷魚游戲的評價生成詞云

    讀萬卷書不如行萬里路,只學(xué)書上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實(shí)戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用Python爬取熱火的魷魚游戲評價,大家可以在過程中查缺補(bǔ)漏,提升水平
    2021-10-10
  • Python使用pyautogui模塊實(shí)現(xiàn)自動化鼠標(biāo)和鍵盤操作示例

    Python使用pyautogui模塊實(shí)現(xiàn)自動化鼠標(biāo)和鍵盤操作示例

    這篇文章主要介紹了Python使用pyautogui模塊實(shí)現(xiàn)自動化鼠標(biāo)和鍵盤操作,簡單描述了pyautogui模塊的功能,并結(jié)合實(shí)例形式較為詳細(xì)的分析了Python使用pyautogui模塊實(shí)現(xiàn)鼠標(biāo)與鍵盤自動化操作相關(guān)技巧,需要的朋友可以參考下
    2018-09-09

最新評論