Python使用atexit模塊實(shí)現(xiàn)Golang的defer功能
在 Go 里面可以通過 defer 語句讓函數(shù)在結(jié)束時(shí)執(zhí)行預(yù)定義好的一些操作,舉個(gè)例子。
package main import "fmt" func main() { defer fmt.Println("高老師總能分享出好東西") fmt.Println("執(zhí)行結(jié)束") /* 執(zhí)行結(jié)束 高老師總能分享出好東西 */ }
這個(gè)功能非常方便,比如打開文件之后可以執(zhí)行 defer fp.Close(),這樣函數(shù)結(jié)束時(shí)會(huì)自動(dòng)關(guān)閉文件句柄。那么在 Python 里面可不可以實(shí)現(xiàn)類似的功能呢?本次來聊一聊 atexit 模塊,它能幫我們實(shí)現(xiàn)類似的效果。
import atexit def exit_func(words): print(words) # 將函數(shù)注冊進(jìn)去 atexit.register(exit_func, "高老師總能分享出好東西") print("Hello") print("World") """ Hello World 高老師總能分享出好東西 """
通過 atexit.register 將函數(shù)注冊進(jìn)去之后,會(huì)在程序結(jié)束之前執(zhí)行,當(dāng)然也可以同時(shí)注冊多個(gè)。
import atexit def exit_func(words): print(words) # 將函數(shù)注冊進(jìn)去 atexit.register(exit_func, "高老師總能分享出好東西") atexit.register(exit_func, "S 老師今年 18,單身帶倆娃") atexit.register(exit_func, "只因^(* ̄(oo) ̄)^只因大(出海版)") print("Hello") print("World") """ Hello World 只因^(* ̄(oo) ̄)^只因大(出海版) S 老師今年 18,單身帶倆娃 高老師總能分享出好東西 """
如果同時(shí)注冊了多個(gè)函數(shù),那么會(huì)按照先入后出的順序執(zhí)行。非常簡單,其實(shí) atexit 模塊就是將我們注冊的函數(shù)保存在了一個(gè)數(shù)組中,程序結(jié)束的時(shí)候,從后往前依次執(zhí)行。
既然可以注冊函數(shù),那么也可以取消注冊。
import atexit def exit_func1(words): print(words) def exit_func2(words): print(words) atexit.register(exit_func1, "高老師總能分享出好東西") atexit.register(exit_func1, "S 老師今年 18,單身帶倆娃") atexit.register(exit_func2, "只因^(* ̄(oo) ̄)^只因大(出海版)") # 取消注冊,所有注冊的 exit_func1 函數(shù)都會(huì)被刪除 atexit.unregister(exit_func1) """ 只因^(* ̄(oo) ̄)^只因大(出海版) """
而它的邏輯也很簡單,就是遍歷數(shù)組,如果和指定的函數(shù)相等,那么就刪掉。我們看一下源代碼。
如果你想將注冊的函數(shù)全部取消掉,那么也可以調(diào)用 _clear() 函數(shù)。
import atexit def exit_func1(words): print(words) def exit_func2(words): print(words) atexit.register(exit_func1, "高老師總能分享出好東西") atexit.register(exit_func1, "S 老師今年 18,單身帶倆娃") atexit.register(exit_func2, "只因^(* ̄(oo) ̄)^只因大(出海版)") atexit._clear()
此時(shí)程序不會(huì)有任何輸出,因?yàn)樽缘暮瘮?shù)全部被清空了,同樣可以看一下它的源代碼。
最后就是函數(shù)的調(diào)用時(shí)機(jī),我們注冊的函數(shù)在程序結(jié)束時(shí)才會(huì)調(diào)用,可不可以讓它們在任意時(shí)刻調(diào)用呢?
import atexit def exit_func1(words): print(words) def exit_func2(words): print(words) atexit.register(exit_func1, "AAA") atexit.register(exit_func1, "BBB") # 調(diào)用注冊的函數(shù),調(diào)用之后函數(shù)會(huì)被刪除 atexit._run_exitfuncs() print("++++++++++++++++") atexit.register(exit_func2, "CCC") atexit._run_exitfuncs() print("----------------") """ BBB AAA ++++++++++++++++ CCC ---------------- """
輸出結(jié)果表明,一旦調(diào)用了 _run_exitfuncs,所有注冊的函數(shù)會(huì)立即被調(diào)用。我們看一下源代碼。
以上就是 atexit 模塊的用法,那我們?nèi)绾位谒鼘?shí)現(xiàn) Golang 的 defer 呢?
from typing import Callable import atexit def defer(func: Callable, *args, **kwargs): atexit.register(func, *args, **kwargs) def get_file_content(file_path): fp = open(file_path, encoding="utf-8") defer(fp.close) # 注冊函數(shù) content = fp.read() # do something ... atexit._run_exitfuncs() # 觸發(fā)注冊函數(shù)執(zhí)行 get_file_content("config.py")
不過這個(gè)例子明顯有點(diǎn)刻意了,因?yàn)楸仨氁诤瘮?shù)的結(jié)尾調(diào)用 atexit._run_exitfuncs,而之所以要實(shí)現(xiàn) Go 的 defer,就是為了避免遺忘某些邏輯。
如果每次都要在函數(shù)結(jié)尾調(diào)用 atexit._run_exitfuncs,那還不如不用,于是我們可以考慮使用裝飾器。
from typing import Callable from functools import wraps import atexit def defer(func: Callable, *args, **kwargs): atexit.register(func, *args, **kwargs) # 給函數(shù)賦予 defer 功能 def enable_defer(func): @wraps(func) def inner(*args, **kwargs): ret = func(*args, **kwargs) atexit._run_exitfuncs() return ret return inner @enable_defer # 通過裝飾器,讓函數(shù)支持 defer 功能 def get_file_content(file_path): fp = open(file_path, encoding="utf-8") # 注冊函數(shù) defer(fp.close) defer(print, "get_file_content 函數(shù)實(shí)現(xiàn)了 defer 功能") content = fp.read() print("函數(shù)執(zhí)行結(jié)束") get_file_content("config.py") print("程序結(jié)束") """ 函數(shù)執(zhí)行結(jié)束 get_file_content 函數(shù)實(shí)現(xiàn)了 defer 功能 程序結(jié)束 """
輸出結(jié)果表明,在函數(shù)結(jié)束后,通過 defer 注冊的函數(shù)執(zhí)行了。
以上就是Python使用atexit模塊實(shí)現(xiàn)Golang的defer功能的詳細(xì)內(nèi)容,更多關(guān)于Python atexit實(shí)現(xiàn)defer功能的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用pytorch提取卷積神經(jīng)網(wǎng)絡(luò)的特征圖可視化
這篇文章主要給大家介紹了關(guān)于使用pytorch提取卷積神經(jīng)網(wǎng)絡(luò)的特征圖可視化的相關(guān)資料,文中給出了詳細(xì)的思路以及示例代碼,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2022-03-03Python+selenium 獲取瀏覽器窗口坐標(biāo)、句柄的方法
今天小編就為大家分享一篇Python+selenium 獲取瀏覽器窗口坐標(biāo)、句柄的方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-10-10對pandas將dataframe中某列按照條件賦值的實(shí)例講解
今天小編就為大家分享一篇對pandas將dataframe中某列按照條件賦值的實(shí)例講解,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-11-11python+openCV對視頻進(jìn)行截取的實(shí)現(xiàn)
這篇文章主要介紹了python+openCV對視頻進(jìn)行截取的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11Python實(shí)現(xiàn)將Excel轉(zhuǎn)換成xml的方法示例
這篇文章主要介紹了Python實(shí)現(xiàn)將Excel轉(zhuǎn)換成xml的方法,涉及Python針對Excel文件的讀取、遍歷、節(jié)點(diǎn)設(shè)置與xml生成等相關(guān)操作技巧,需要的朋友可以參考下2018-08-08Python實(shí)現(xiàn)程序的單一實(shí)例用法分析
這篇文章主要介紹了Python實(shí)現(xiàn)程序的單一實(shí)例用法,較為詳細(xì)的分析了Python窗口的相關(guān)操作技巧,需要的朋友可以參考下2015-06-06如何配置關(guān)聯(lián)Python 解釋器 Anaconda的教程(圖解)
這篇文章主要介紹了如何配置關(guān)聯(lián)Python 解釋器 Anaconda的教程,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)火鍋工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04