日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > python >内容正文

python

python装饰器源代码_13-Python-装饰器

發(fā)布時(shí)間:2023/12/4 python 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python装饰器源代码_13-Python-装饰器 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1、裝飾器的定義

裝飾器的本質(zhì)就是函數(shù),用來(lái)裝飾其它函數(shù),就是為其它函數(shù)添加附加功能。

裝飾器原則如下:

不能修改被裝飾的函數(shù)的源代碼

不能修改被裝飾的函數(shù)的調(diào)用方式

2、實(shí)現(xiàn)裝飾器知識(shí)儲(chǔ)備

函數(shù)即變量

1 defbar():2 print("in the bar")3 deffoo():4 print("in the foo")5 bar()6

7 foo()8

9 print("----------分割線-----------")10

11 deffoo1():12 print("in the foo")13 bar1()14 defbar1():15 print("in the bar")16

17 foo1()18

19 print("----------分割線-----------")20 #這樣會(huì)報(bào)錯(cuò)

21 #def foo2():

22 #print("in the foo")

23 #bar2()

24 #foo2()

25 #def bar2():

26 #print("in the bar")

高階函數(shù)

把一個(gè)函數(shù)名當(dāng)作實(shí)參傳遞給另外一個(gè)函數(shù)(在不修改被裝飾函數(shù)源代碼的情況下為其添加功能)

1 importtime2

3 defbar1():4 time.sleep(3)5 print("in the bar")6

7 deftest2(func):8 start_time =time.time()9 func() #相當(dāng)于運(yùn)行bar1()

10 stop_time =time.time()11 print("total run time %s" %(stop_time -start_time))12

13 test2(bar1)

返回值中包含函數(shù)名(不能修改函數(shù)的調(diào)用方式)

1 defbar2():2 time.sleep(3)3 print("in the bar2")4

5 deftest3(func):6 print(func)7 returnfunc8

9 print(test3(bar2)) #獲取的是內(nèi)存地址

10

11 res =test3(bar2)12 res()

嵌套函數(shù)

1 deffoo():2 print("in the foo")3 defbar():4 print("in the bar")5 bar() #局部變量只能在其作用域內(nèi)調(diào)用

6

7 foo()

1 x =02 defgrandpa():3 x = 1

4 defdad():5 x = 2

6 defson():7 x = 3

8 print(x) #最終打印結(jié)果為3

9 son()10 dad()11 grandpa()

高階函數(shù) + 嵌套函數(shù) --》裝飾器

1 importtime2

3

4 deftimer(func):5 defdeco():6 start_time =time.time()7 func()8 stop_time =time.time()9 print("total time is %s" % (stop_time -start_time))10 return deco #返回deco()的內(nèi)存地址

11

12

13 deftest1():14 time.sleep(3)15 print("in the test1")16

17

18 deftest2():19 time.sleep(3)20 print("in the test2")21

22 #以下可直接用裝飾器語(yǔ)法代替

23 timer(test1) #test1的內(nèi)存地址賦值給func,返回deco()的內(nèi)存地址

24 print(timer(test1)) #返回deco()的內(nèi)存地址

25 test1 = timer(test1) #內(nèi)存地址賦值給test1

26 test1() #相當(dāng)于執(zhí)行deco()

27

28 timer(test2)29 test2 =timer(test2)30 test2()31

32 print("---------我是分隔符---------")33

34

35 #裝飾器語(yǔ)法如下。(和上面引用的效果一樣)

36 @timer #相當(dāng)于test1 = timer(test1)

37 deftest1():38 time.sleep(3)39 print("in the test1")40

41

42 @timer #相當(dāng)于test1 = timer(test1)43 deftest2():44 time.sleep(3)45 print("in the test2")46

47

48 test1()49 test2()

3、動(dòng)態(tài)參數(shù)裝飾器

deftimer(bar):def inner(*args, **kwargs):

start_time=time.time()

foo_ret= bar(*args, **kwargs)

end_time=time.time()

used_time= end_time -start_timeprint(used_time)returnfoo_retreturninner

@timerdef foo(*args, **kwargs):

time.sleep(1)print("我的參數(shù):", args, kwargs)print("我的運(yùn)行時(shí)間:")return "我的返回值"ret= foo("動(dòng)態(tài)參數(shù)裝飾器", (1, 2), name="Druid", age=18)print(ret)

輸出結(jié)果如下:

4、裝飾器原理圖解

4.1 被裝飾函數(shù)沒(méi)有返回值

4.2 被裝飾函數(shù)有返回值

注意:第二步僅為過(guò)程分析量,不作為真實(shí)的執(zhí)行順序。

5、裝飾器固定格式

裝飾器的固定格式如下例所示:

defwrapper(func):"""該函數(shù)為裝飾器函數(shù)

:param func: 這里的func參數(shù)實(shí)質(zhì)是指向被裝飾函數(shù)的內(nèi)存地址

:return:"""

def inner(*args, **kwargs):"""該函數(shù)為裝飾器函數(shù)內(nèi)部函數(shù)

:param args: 實(shí)質(zhì)接收的是被裝飾函數(shù)的位置參數(shù)

:param kwargs: 實(shí)質(zhì)接收的是被裝飾函數(shù)的關(guān)鍵字參數(shù)

:return: 返回的是被裝飾函數(shù)的返回值"""

print("這里放被裝飾函數(shù)執(zhí)行之前要做的事")

func_ret= func(*args, **kwargs) #被裝飾的函數(shù)

print("這里放被裝飾函數(shù)執(zhí)行之后要做的事")returnfunc_retreturninner

@wrapper#等價(jià)于my_func = wrapper(my_func)

def my_func(*args, **kwargs):"""該函數(shù)為被裝飾函數(shù)

:param args: 接收位置參數(shù)

:param kwargs: 接收關(guān)鍵字參數(shù)

:return: 返回值"""

print(*args, **kwargs)returnret

ret= my_func() #執(zhí)行原函數(shù),實(shí)質(zhì)是執(zhí)行inner()。函數(shù)返回值保存在變量ret中。

6、裝飾器修復(fù)

當(dāng)我們使用裝飾器去裝飾某個(gè)函數(shù)時(shí),我們想要引用被裝飾函數(shù)原私有屬性,如__name__、__doc__時(shí),就有問(wèn)題了,因?yàn)槲覀冸m然仍然在執(zhí)行被裝飾函數(shù),但其實(shí)執(zhí)行的是閉包,看下例。

defwrapper(func):"""該函數(shù)為裝飾器函數(shù)

:param func: 這里的func參數(shù)實(shí)質(zhì)是指向被裝飾函數(shù)的內(nèi)存地址

:return:"""

def inner(*args, **kwargs):"""該函數(shù)為閉包(裝飾器函數(shù)內(nèi)部函數(shù))

:param args: 實(shí)質(zhì)接收的是被裝飾函數(shù)的位置參數(shù)

:param kwargs: 實(shí)質(zhì)接收的是被裝飾函數(shù)的關(guān)鍵字參數(shù)

:return: 返回的是被裝飾函數(shù)的返回值"""func_ret= func(*args, **kwargs) #被裝飾的函數(shù)

returnfunc_retreturninner

@wrapper#等價(jià)于my_func = wrapper(my_func)

def my_func(*args, **kwargs):"""該函數(shù)為被裝飾函數(shù)

:param args: 接收位置參數(shù)

:param kwargs: 接收關(guān)鍵字參數(shù)

:return: 返回值"""

print(*args, **kwargs)return "返回值"my_func("裝飾器沒(méi)被修復(fù)前,被裝飾函數(shù)原函數(shù)的私有屬性如__name__、__doc__是獲取不到的,如下:") #執(zhí)行原函數(shù),實(shí)質(zhì)是執(zhí)行inner()

print(my_func.__name__) #打印函數(shù)的名字

print(my_func.__doc__) #打印函數(shù)的注釋文檔

輸出結(jié)果如下:

如果仍想使用被裝飾函數(shù)的原私有屬性,那么就可以用裝飾器修復(fù):

from functools importwrapsdefwrapper(func):"""該函數(shù)為裝飾器函數(shù)

:param func: 這里的func參數(shù)實(shí)質(zhì)是指向被裝飾函數(shù)的內(nèi)存地址

:return:"""@wraps(func)def inner(*args, **kwargs):"""該函數(shù)為閉包(裝飾器函數(shù)內(nèi)部函數(shù))

:param args: 實(shí)質(zhì)接收的是被裝飾函數(shù)的位置參數(shù)

:param kwargs: 實(shí)質(zhì)接收的是被裝飾函數(shù)的關(guān)鍵字參數(shù)

:return: 返回的是被裝飾函數(shù)的返回值"""func_ret= func(*args, **kwargs) #被裝飾的函數(shù)

print("裝飾器修復(fù)不會(huì)改變?cè)b飾器的作用")returnfunc_retreturninner

@wrapper#等價(jià)于my_func = wrapper(my_func)

def my_func(*args, **kwargs):"""該函數(shù)為被裝飾函數(shù)

:param args: 接收位置參數(shù)

:param kwargs: 接收關(guān)鍵字參數(shù)

:return: 返回值"""

print(*args, **kwargs)return "返回值"my_func("裝飾器被修復(fù)后,被裝飾函數(shù)原函數(shù)的私有屬性如__name__、__doc__就可以正常獲取了,如下:") #執(zhí)行原函數(shù),實(shí)質(zhì)是執(zhí)行inner()

print(my_func.__name__) #打印函數(shù)的名字

print(my_func.__doc__) #打印函數(shù)的注釋文檔

輸出結(jié)果如下:

7、帶參數(shù)的裝飾器

需求:很多函數(shù)共用一個(gè)裝飾器,要求隨時(shí)可以關(guān)閉裝飾器功能,且盡可能的減少代碼修改。 該需求可以用標(biāo)記位來(lái)實(shí)現(xiàn),如下:

importtime

FLAG=Truedeftimmer_out(flag):deftimmer(func):def inner(*args, **kwargs):ifflag:

start_time=time.time()

ret_func= func(*args, **kwargs)

end_time=time.time()

used_time= end_time -start_timeprint("函數(shù){name}執(zhí)行時(shí)間:{time}".format(name=func.__name__, time=used_time))#print("函數(shù){name}執(zhí)行時(shí)間:{time}".format_map({"name": func.__name__, "time": used_time}))

else:

ret_func= func(*args, **kwargs)returnret_funcreturninnerreturntimmer

@timmer_out(FLAG)#第一步,先執(zhí)行timmer_out(FLAG),得到返回值timmer。第二步執(zhí)行@timmer,即 my_func1 = timmer(my_func1)

defmy_func1():

time.sleep(1)print("my_func1")

@timmer_out(FLAG)defmy_func2():

time.sleep(1)print("my_func2")

@timmer_out(FLAG)defmy_func3():

time.sleep(1)print("my_func3")

my_func1()

my_func2()

my_func3()

當(dāng)FLAG置為T(mén)rue時(shí),裝飾器功能生效,輸出結(jié)果如下圖所示:

當(dāng)FLAG置為False時(shí),裝飾器功能關(guān)閉,輸出結(jié)果如下圖所示:

8、多個(gè)裝飾器裝飾一個(gè)函數(shù)

defwrapper1(func):definner1():print("wrapper1, before func")

func()print("wrapper1, after func")returninner1defwrapper2(func):definner2():print("wrapper2, before func")

func()print("wrapper2, after func")returninner2

@wrapper2

@wrapper1defmy_func():print("function is my func")

my_func()

注意輸出結(jié)果:

為什么結(jié)果是這樣?請(qǐng)看如下分析:

為什么是先執(zhí)行@wrapper1而不是@wrapeer2呢?因?yàn)檠b飾器在找到被裝飾函數(shù)會(huì)優(yōu)先執(zhí)行。

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的python装饰器源代码_13-Python-装饰器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。