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

詳解如何利用Python裝飾器優(yōu)化代碼

 更新時(shí)間:2023年05月09日 09:13:34   作者:簡(jiǎn)說(shuō)Python  
這篇文章主要帶大家深入探討裝飾器的應(yīng)用,包括計(jì)時(shí)器裝飾器和緩存裝飾器等的實(shí)現(xiàn),文中的示例代碼講解詳細(xì),需要的小伙伴可以參考下

本文將帶你深入探討裝飾器的應(yīng)用,包括計(jì)時(shí)器裝飾器和緩存裝飾器等的實(shí)現(xiàn)。通過(guò)這些案例,我們可以看到裝飾器的強(qiáng)大和靈活,它們可以幫助我們優(yōu)化代碼,提高性能,讓我們的程序更加健壯和高效。

你是不是經(jīng)常發(fā)現(xiàn)自己寫(xiě) Python 代碼很冗余?或者已經(jīng)寫(xiě)了一些簡(jiǎn)潔的代碼,但是正常運(yùn)行時(shí)卻會(huì)遇到性能問(wèn)題?那么,Python 裝飾器就是你的救星!本文將帶你深入探討裝飾器的應(yīng)用,包括計(jì)時(shí)器裝飾器和緩存裝飾器的實(shí)現(xiàn)。

什么是裝飾器

先來(lái)了解一下什么是裝飾器。

裝飾器是 Python 的一個(gè)重要特性,它允許你將一個(gè)函數(shù)作為參數(shù)傳遞給另一個(gè)函數(shù),并返回一個(gè)新的函數(shù),而不對(duì)原始函數(shù)進(jìn)行修改。這使得你可以在不改變代碼本身的情況下,動(dòng)態(tài)地修改函數(shù)的行為。下面我們會(huì)通過(guò)具體的案例來(lái)進(jìn)一步解釋這個(gè)概念。

裝飾器的應(yīng)用

直接通過(guò)案例來(lái)理解和使用裝飾器。

計(jì)時(shí)器裝飾器

計(jì)時(shí)器裝飾器可以幫助你在代碼運(yùn)行時(shí)自動(dòng)計(jì)時(shí),以便你了解代碼的性能。下面是一個(gè)例子:

import?time

#?定義計(jì)時(shí)器裝飾器
def?timer_decorator(func):
????#?定義內(nèi)部包裝函數(shù),用于接收任意數(shù)量的位置參數(shù)和關(guān)鍵字參數(shù)
????def?wrapper(*args,?**kwargs):
????????#?記錄函數(shù)運(yùn)行開(kāi)始時(shí)間
????????start_time?=?time.time()
????????#?調(diào)用原始函數(shù)并將結(jié)果存儲(chǔ)在result中
????????result?=?func(*args,?**kwargs)
????????#?記錄函數(shù)運(yùn)行結(jié)束時(shí)間
????????end_time?=?time.time()
????????#?計(jì)算函數(shù)運(yùn)行時(shí)間并打印結(jié)果
????????print(f"函數(shù)?{func.__name__}?運(yùn)行時(shí)間為?{end_time?-?start_time}?秒")
????????#?返回原始函數(shù)的結(jié)果
????????return?result
????#?返回包裝函數(shù)
????return?wrapper

@timer_decorator
def?slow_function():
????time.sleep(2)
????print("使用?timer_decorator?計(jì)算下?slow_function?函數(shù)的運(yùn)行時(shí)長(zhǎng)")

slow_function()

在上面的例子中,我們定義了一個(gè)計(jì)時(shí)器裝飾器 timer_decorator,并將它應(yīng)用到一個(gè)簡(jiǎn)單函數(shù) slow_function 上。當(dāng)我們調(diào)用 slow_function 時(shí),計(jì)時(shí)器會(huì)自動(dòng)開(kāi)始計(jì)時(shí),并在函數(shù)執(zhí)行完畢后輸出函數(shù)的運(yùn)行時(shí)間。

緩存裝飾器

緩存裝飾器可以幫助你避免重復(fù)計(jì)算,以提高代碼的性能。下面是一個(gè)例子,使用了一個(gè)緩存裝飾器來(lái)優(yōu)化遞歸斐波那契數(shù)列計(jì)算:

#?定義緩存裝飾器
def?cache_decorator(func):
????#?創(chuàng)建一個(gè)字典來(lái)存儲(chǔ)緩存的結(jié)果
????cache?=?dict()
????#?定義內(nèi)部包裝函數(shù),用于接收任意數(shù)量的位置參數(shù)
????def?wrapper(*args):
????????#?檢查當(dāng)前參數(shù)是否在緩存中
????????if?args?in?cache:
????????????#?如果在緩存中,則從緩存中獲取結(jié)果并打印提示信息
????????????print(f"從緩存中獲取?{args}?的結(jié)果")
????????????return?cache[args]
????????#?如果不在緩存中,則調(diào)用原始函數(shù)計(jì)算結(jié)果
????????result?=?func(*args)
????????#?將計(jì)算結(jié)果存儲(chǔ)到緩存中,并打印提示信息
????????cache[args]?=?result
????????print(f"計(jì)算?{args}?的結(jié)果并將其存入緩存")
????????#?返回計(jì)算結(jié)果
????????return?result
????#?返回包裝函數(shù)
????return?wrapper
#?使用緩存裝飾器修飾fibonacci函數(shù)
@cache_decorator
def?fibonacci(n):
????if?n?<?2:
????????return?n
????else:
????????return?fibonacci(n-1)?+?fibonacci(n-2)
print(fibonacci(3))
print("*****************")
print(fibonacci(5))

在上面的例子中,我們定義了一個(gè)緩存裝飾器 cache_decorator,并將它應(yīng)用到一個(gè)計(jì)算斐波那契數(shù)列的函數(shù) fibonacci 上。當(dāng)我們多次調(diào)用 fibonacci 函數(shù)時(shí),緩存裝飾器會(huì)自動(dòng)檢查緩存中是否已經(jīng)計(jì)算了該值,如果已經(jīng)計(jì)算則直接返回緩存中的值,否則進(jìn)行計(jì)算并將結(jié)果存入緩存。

類(lèi)型檢查裝飾器

類(lèi)型檢查裝飾器可以幫助你在函數(shù)調(diào)用時(shí)自動(dòng)檢查參數(shù)類(lèi)型,以便你避免傳入錯(cuò)誤的參數(shù)。下面是一個(gè)例子:

#?定義類(lèi)型檢查裝飾器
def?type_check_decorator(func):
????#?定義內(nèi)部包裝函數(shù),用于接收任意數(shù)量的位置參數(shù)和關(guān)鍵字參數(shù)
????def?wrapper(*args,?**kwargs):
????????#?遍歷位置參數(shù)
????????for?i,?arg?in?enumerate(args):
????????????#?如果參數(shù)不是字符串類(lèi)型,拋出TypeError異常
????????????if?not?isinstance(arg,?str):
????????????????raise?TypeError(f"第?{i+1}?個(gè)參數(shù)值?{arg}?必須是?str?類(lèi)型")
????????#?遍歷關(guān)鍵字參數(shù)
????????for?key,?value?in?kwargs.items():
????????????#?如果關(guān)鍵字參數(shù)的值不是字符串類(lèi)型,拋出TypeError異常
????????????if?not?isinstance(value,?str):
????????????????raise?TypeError(f"關(guān)鍵字參數(shù)?{key}?必須是?str?類(lèi)型")
????????#?參數(shù)檢查通過(guò)后,調(diào)用原始函數(shù)并返回結(jié)果
????????return?func(*args,?**kwargs)
????#?返回包裝函數(shù)
????return?wrapper
#?使用類(lèi)型檢查裝飾器修飾concat_strings函數(shù)
@type_check_decorator
def?concat_strings(*strings,?sep="?"):
????return?sep.join(strings)

在上面的例子中,我們定義了一個(gè)類(lèi)型檢查裝飾器 type_check_decorator,并將它應(yīng)用到一個(gè)將多個(gè)字符串拼接為一個(gè)字符串的函數(shù) concat_strings 上。當(dāng)我們調(diào)用 concat_strings 時(shí),類(lèi)型檢查裝飾器會(huì)自動(dòng)檢查參數(shù)類(lèi)型,并在參數(shù)類(lèi)型錯(cuò)誤時(shí)拋出異常。

日志裝飾器

日志裝飾器可以幫助你在代碼執(zhí)行時(shí)自動(dòng)記錄日志,以便你了解代碼的執(zhí)行情況。下面是一個(gè)例子:

import?logging
#?定義日志裝飾器
def?log_decorator(func):
????#?配置日志記錄器,將日志記錄到文件example.log,日志級(jí)別為INFO
????logging.basicConfig(filename="example.log",?level=logging.INFO)
????#?定義內(nèi)部包裝函數(shù),用于接收任意數(shù)量的位置參數(shù)和關(guān)鍵字參數(shù)
????def?wrapper(*args,?**kwargs):
????????#?記錄函數(shù)調(diào)用信息到日志文件中
????????logging.info(f"Calling?function?{func.__name__}")
????????#?調(diào)用原始函數(shù)并將結(jié)果存儲(chǔ)在result中
????????result?=?func(*args,?**kwargs)
????????#?記錄函數(shù)返回值信息到日志文件中
????????logging.info(f"Function?{func.__name__}?returned?{result}")
????????#?返回原始函數(shù)的結(jié)果
????????return?result
????#?返回包裝函數(shù)
????return?wrapper
#?使用日志裝飾器修飾add函數(shù)
@log_decorator
def?add(a,?b):
????return?a?+?b
#?調(diào)用add函數(shù)并打印結(jié)果
print(add(1,?2))

在上面的例子中,我們定義了一個(gè)日志裝飾器 log_decorator,并將它應(yīng)用到一個(gè)加法函數(shù) add 上。當(dāng)我們調(diào)用 add 時(shí),日志裝飾器會(huì)自動(dòng)記錄日志,并將日志信息寫(xiě)入到指定的文件中。

授權(quán)裝飾器

授權(quán)裝飾器可以幫助你在函數(shù)調(diào)用時(shí)自動(dòng)檢查用戶權(quán)限,以便你避免未授權(quán)的用戶訪問(wèn)敏感數(shù)據(jù)。下面是一個(gè)例子:

#?定義一個(gè)高階函數(shù),接受一個(gè)所需角色列表作為參數(shù)
def?roles_required(required_roles):
????#?定義授權(quán)裝飾器
????def?authorization_decorator(func):
????????#?定義包裝函數(shù),用于接收任意數(shù)量的位置參數(shù)和關(guān)鍵字參數(shù)
????????def?wrapper(*args,?**kwargs):
????????????#?獲取用戶角色,默認(rèn)為"guest"
????????????user_role?=?kwargs.get("user_role",?"guest")
????????????#?檢查用戶角色是否在所需角色列表中
????????????if?user_role?not?in?required_roles:
????????????????#?如果不在列表中,拋出一個(gè)?PermissionError?異常
????????????????raise?PermissionError(f"訪問(wèn)被拒絕:?需要?{',?'.join(required_roles)}?其中之一的角色")
????????????#?如果用戶角色在所需角色列表中,調(diào)用原始函數(shù)并返回結(jié)果
????????????return?func(*args,?**kwargs)
????????#?返回包裝函數(shù)
????????return?wrapper
????#?返回授權(quán)裝飾器
????return?authorization_decorator
#?使用?roles_required?裝飾器,允許?admin?和?user?角色的用戶訪問(wèn)受保護(hù)的功能
@roles_required(["admin",?"user"])
def?protected_function(user_role="guest"):
????print("受保護(hù)的功能已成功執(zhí)行")
#?嘗試使用?guest?角色訪問(wèn)受保護(hù)的功能
try:
????protected_function(user_role="guest")
except?PermissionError?as?e:
????print(e)
#?嘗試使用?user?角色訪問(wèn)受保護(hù)的功能
try:
????protected_function(user_role="user")
except?PermissionError?as?e:
????print(e)
#?嘗試使用?admin?角色訪問(wèn)受保護(hù)的功能
try:
????protected_function(user_role="admin")
except?PermissionError?as?e:
????print(e)

在上面的例子中,我們首先定義了一個(gè)名為roles_required的高階函數(shù),它接受一個(gè)required_roles列表參數(shù)。該高階函數(shù)返回一個(gè)名為authorization_decorator的裝飾器,該裝飾器定義了一個(gè)名為wrapper的內(nèi)部函數(shù),用于檢查用戶角色是否在所需角色列表中。如果用戶角色在列表中,裝飾器將調(diào)用原始函數(shù)并返回結(jié)果;否則,它將拋出一個(gè)PermissionError異常。

我們使用@roles_required(["admin", "user"])裝飾器來(lái)修飾protected_function,確保只有具有admin或user角色的用戶可以訪問(wèn)該功能。然后,我們嘗試使用不同角色的用戶訪問(wèn)受保護(hù)的功能,以驗(yàn)證裝飾器的功能。

拓展

在上面的案例中,我們用到了兩個(gè)額外功能:高階函數(shù)和包裝器。這兩個(gè)概念在Python裝飾器的實(shí)現(xiàn)中起到了關(guān)鍵作用。接下來(lái),我們?cè)敿?xì)介紹它們的作用和應(yīng)用:

高階函數(shù)

高階函數(shù)是指接收一個(gè)或多個(gè)函數(shù)作為參數(shù)并返回一個(gè)新函數(shù)的函數(shù)。在我們的示例中,roles_required函數(shù)是一個(gè)高階函數(shù)。它接收一個(gè)所需角色列表作為參數(shù),并返回一個(gè)名為authorization_decorator的裝飾器函數(shù)。

高階函數(shù)在函數(shù)式編程中具有重要作用,因?yàn)樗鼈冊(cè)试S我們將函數(shù)作為參數(shù)傳遞,從而提高代碼的靈活性和復(fù)用性。

高階函數(shù)的應(yīng)用:

  • 實(shí)現(xiàn)代碼復(fù)用和模塊化
  • 簡(jiǎn)化代碼結(jié)構(gòu),提高代碼可讀性
  • 實(shí)現(xiàn)函數(shù)式編程范式,支持函數(shù)作為參數(shù)傳遞和返回值

包裝器

包裝器(Wrapper)是一個(gè)用于修改其他函數(shù)行為的函數(shù)。在我們的示例中,wrapper函數(shù)是一個(gè)包裝器。它接收任意數(shù)量的位置參數(shù)和關(guān)鍵字參數(shù),然后根據(jù)特定邏輯(在這個(gè)例子中是檢查用戶角色)來(lái)決定是否調(diào)用原始函數(shù)(即被裝飾的函數(shù))。

包裝器的應(yīng)用:

  • 修改或增強(qiáng)原始函數(shù)的行為,而無(wú)需修改原始函數(shù)的代碼
  • 實(shí)現(xiàn)代碼的解耦,將不同功能分開(kāi)
  • 提高代碼的可讀性和可維護(hù)性

在裝飾器中,高階函數(shù)和包裝器共同發(fā)揮作用。高階函數(shù)負(fù)責(zé)接收參數(shù)并生成裝飾器,而裝飾器內(nèi)部的包裝器負(fù)責(zé)根據(jù)特定邏輯對(duì)原始函數(shù)進(jìn)行修改或增強(qiáng)。這種組合提供了一種靈活且強(qiáng)大的方式來(lái)擴(kuò)展和修改函數(shù)的行為,同時(shí)保持代碼的模塊化和易于維護(hù)。

總結(jié)

本文介紹了 Python 裝飾器的基本概念和幾種常見(jiàn)的應(yīng)用場(chǎng)景:計(jì)時(shí)器裝飾器和緩存裝飾器等。通過(guò)這些案例,我們可以看到裝飾器的強(qiáng)大和靈活,它們可以幫助我們優(yōu)化代碼,提高性能,讓我們的程序更加健壯和高效。

到此這篇關(guān)于詳解如何利用Python裝飾器優(yōu)化代碼的文章就介紹到這了,更多相關(guān)Python裝飾器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論