成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

通過 Atexit 模塊讓 Python 實現 Golang 的 defer 功能,你學會了嗎?

開發 前端
如果同時注冊了多個函數,那么會按照先入后出的順序執行。非常簡單,其實 atexit 模塊就是將我們注冊的函數保存在了一個數組中,程序結束的時候,從后往前依次執行。

在 Go 里面可以通過 defer 語句讓函數在結束時執行預定義好的一些操作,舉個例子。

package main

import "fmt"

func main() {
    defer fmt.Println("高老師總能分享出好東西")
    fmt.Println("執行結束")
    /*
    執行結束
    高老師總能分享出好東西
    */
}

這個功能非常方便,比如打開文件之后可以執行 defer fp.Close(),這樣函數結束時會自動關閉文件句柄。那么在 Python 里面可不可以實現類似的功能呢?本次來聊一聊 atexit 模塊,它能幫我們實現類似的效果。

import atexit

def exit_func(words):
    print(words)

# 將函數注冊進去
atexit.register(exit_func, "高老師總能分享出好東西")
print("Hello")
print("World")
"""
Hello
World
高老師總能分享出好東西
"""

通過 atexit.register 將函數注冊進去之后,會在程序結束之前執行,當然也可以同時注冊多個。

import atexit

def exit_func(words):
    print(words)

# 將函數注冊進去
atexit.register(exit_func, "高老師總能分享出好東西")
atexit.register(exit_func, "S 老師今年 18,單身帶倆娃")
atexit.register(exit_func, "只因^(* ̄(oo) ̄)^只因大(出海版)")
print("Hello")
print("World")
"""
Hello
World
只因^(* ̄(oo) ̄)^只因大(出海版)
S 老師今年 18,單身帶倆娃
高老師總能分享出好東西
"""

如果同時注冊了多個函數,那么會按照先入后出的順序執行。非常簡單,其實 atexit 模塊就是將我們注冊的函數保存在了一個數組中,程序結束的時候,從后往前依次執行。

圖片圖片

既然可以注冊函數,那么也可以取消注冊。

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 函數都會被刪除
atexit.unregister(exit_func1)
"""
只因^(* ̄(oo) ̄)^只因大(出海版)
"""

而它的邏輯也很簡單,就是遍歷數組,如果和指定的函數相等,那么就刪掉。我們看一下源代碼。

圖片圖片

如果你想將注冊的函數全部取消掉,那么也可以調用 _clear() 函數。

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()

此時程序不會有任何輸出,因為注冊的函數全部被清空了,同樣可以看一下它的源代碼。

圖片圖片

最后就是函數的調用時機,我們注冊的函數在程序結束時才會調用,可不可以讓它們在任意時刻調用呢?

import atexit

def exit_func1(words):
    print(words)

def exit_func2(words):
    print(words)

atexit.register(exit_func1, "AAA")
atexit.register(exit_func1, "BBB")
# 調用注冊的函數,調用之后函數會被刪除
atexit._run_exitfuncs()
print("++++++++++++++++")

atexit.register(exit_func2, "CCC")
atexit._run_exitfuncs()
print("----------------")
"""
BBB
AAA
++++++++++++++++
CCC
----------------
"""

輸出結果表明,一旦調用了 _run_exitfuncs,所有注冊的函數會立即被調用。我們看一下源代碼。

圖片圖片

以上就是 atexit 模塊的用法,那我們如何基于它實現 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)  # 注冊函數
    content = fp.read()
    # do something
    ...
    atexit._run_exitfuncs()  # 觸發注冊函數執行

get_file_content("config.py")

不過這個例子明顯有點刻意了,因為必須要在函數的結尾調用 atexit._run_exitfuncs,而之所以要實現 Go 的 defer,就是為了避免遺忘某些邏輯。

如果每次都要在函數結尾調用 atexit._run_exitfuncs,那還不如不用,于是我們可以考慮使用裝飾器。

from typing import Callable
from functools import wraps
import atexit

def defer(func: Callable, *args, **kwargs):
    atexit.register(func, *args, **kwargs)

# 給函數賦予 defer 功能
def enable_defer(func):
    @wraps(func)
    def inner(*args, **kwargs):
        ret = func(*args, **kwargs)
        atexit._run_exitfuncs()
        return ret
    return inner

@enable_defer  # 通過裝飾器,讓函數支持 defer 功能
def get_file_content(file_path):
    fp = open(file_path, encoding="utf-8")
    # 注冊函數
    defer(fp.close)
    defer(print, "get_file_content 函數實現了 defer 功能")

    content = fp.read()
    print("函數執行結束")

get_file_content("config.py")
print("程序結束")
"""
函數執行結束
get_file_content 函數實現了 defer 功能
程序結束
"""

輸出結果表明,在函數結束后,通過 defer 注冊的函數執行了。

以上就是用 Python 實現 Go 的 defer,不過在工作中還是不建議這么做,沒啥必要,這里只是想分享一下 atexit 模塊。

責任編輯:武曉燕 來源: 古明地覺的編程教室
相關推薦

2022-11-02 07:37:07

WebAssembl瀏覽器服務器

2022-08-29 08:05:44

Go類型JSON

2022-06-16 07:50:35

數據結構鏈表

2022-09-26 08:49:11

Java架構CPU

2024-07-29 10:35:44

KubernetesCSI存儲

2023-03-10 22:08:20

2022-07-08 09:27:48

CSSIFC模型

2024-01-19 08:25:38

死鎖Java通信

2024-02-04 00:00:00

Effect數據組件

2023-07-26 13:11:21

ChatGPT平臺工具

2023-01-10 08:43:15

定義DDD架構

2024-03-12 08:37:32

asyncawaitJavaScript

2023-12-07 12:29:49

Nginx負載均衡策略

2024-11-28 10:32:32

2024-02-07 01:47:47

atexit模塊程序

2024-02-02 11:03:11

React數據Ref

2023-08-01 12:51:18

WebGPT機器學習模型

2024-01-02 12:05:26

Java并發編程

2024-10-28 00:00:03

IP屬地地址

2023-10-10 11:04:11

Rust難點內存
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美在线一区二区三区 | 亚洲综合色丁香婷婷六月图片 | 99re视频在线观看 | 亚洲免费视频一区 | 亚洲午夜三级 | 国内精品视频在线观看 | 国产毛片久久久久久久久春天 | 狠狠干综合视频 | 成人在线不卡 | 99久久精品国产一区二区三区 | 精品1区 | 欧美久久精品一级黑人c片 91免费在线视频 | 一区二区三区视频 | 中文在线亚洲 | 福利视频一区二区三区 | 国产色婷婷精品综合在线播放 | 色欧美片视频在线观看 | 中文字幕精品视频在线观看 | 91精品国产日韩91久久久久久 | 久久久久久久久淑女av国产精品 | 99精品国产一区二区三区 | 国产免费va | 国产精品高清在线 | 精品国产一区二区三区免费 | 成人精品国产一区二区4080 | 色爱区综合| 免费成人高清在线视频 | 亚洲激情网站 | 国产精品自产拍在线观看蜜 | 亚洲欧美中文日韩在线v日本 | 成人精品一区二区三区四区 | 日韩av成人 | 蜜桃精品视频在线 | www.一区二区三区 | 91精品国产乱码久久久久久久久 | 免费观看一区二区三区毛片 | 蜜桃视频在线观看免费视频网站www | 日本一区二区高清不卡 | 波多野结衣二区 | 国产免费一级一级 | 亚洲成人一区 |