Python也可以拥有延迟函数

本文介绍了Golang中的延迟函数defer的特性和用途,并探讨了如何在Python中模拟实现类似功能。通过使用contextlib中的ExitStack类,可以实现类似defer的功能,确保资源的正确释放,无论函数是否异常退出。文章提供了类版本和装饰器版本的实现方式。
摘要由CSDN通过智能技术生成

延迟函数defer

我们知道在Golang中有一个关键字defer,用它来声明在函数调用前,会让函数*延迟**到外部函数退出时再执行,注意,这里的退出含义:函数return返回或者函数panic退出

defer的特性

  1. defer函数会在外层函数执行结束后执行
package main

import "fmt"

func main() {
	defer fmt.Println(2)
	fmt.Println(1)

}
/* output:
1
2
*/
  1. defer函数会在外层函数异常退出时执行
package main

import "fmt"

func main() {
	defer fmt.Println(2)
	panic(1)

}
/* output:
2
panic: 1

goroutine 1 [running]:
main.main()
	/tmp/sandbox740231192/prog.go:7 +0x95
*/

3.如果函数中有多个defer函数,它们的执行顺序是LIFO:

package main

import "fmt"

func main() {
	defer fmt.Println(2)
	defer fmt.Println(3)
	fmt.Println(1)
}
/*output:
1
3
2
*/

defer的用途

释放资源

比如打开文件后关闭文件:

package main

import "os"

func main() {
	file, err := os.Open("1.txt")
	if err != nil {
		return
	}
        // 关闭文件
	defer file.Close()

	// Do something...

}

又比如数据库操作操作后取消连接

func createPost(db *gorm.DB) error {
    conn := db.Conn()
    defer db.Close()
    
    err := conn.Create(&Post{Author: "Draveness"}).Error

    return err
}

recover恢复

package main

import "fmt"

func main() {
    defer func() {
        if ok := recover(); ok != nil {
            fmt.Println("recover")
        }
    }()

    panic("error")
}
/*output:
recover
*/

总结

  1. defer函数总会被执行,无论外层函数是正常退出还是异常panic
  2. 如果函数中有多个defer函数,它们的执行顺序是LIFO

在Python中的写一个defer

看到defer这么好用,Pythoneer也可以拥有吗?当然

家里(Python)的条件

Python中有一个库叫做contextlib,它有一个类叫ExitStack,来看一下官网的介绍

A context manager that is designed to make it easy to programmatically combine other context managers and cleanup functions, especially those that are optional or otherwise driven by input data.
Since registered callbacks are invoked in the reverse order of registration, this ends up behaving as if multiple nested with statements had been used with the registered set of callbacks. This even extends to exception handling - if an inner callback suppresses or replaces an exception, then outer callbacks will be passed arguments based on that updated state.

Since registered callbacks are invoked in the reverse order of registration 这句是关键,他说注册的回调函数是以注册顺序相反的顺序被调用,这不就是defer函数的第二个特性LIFO吗?

再看下ExitStack类:

class ExitStack
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值