Python__Enter__/__Exit__vs__init__(或__new__)/__del__

Python __enter__ / __exit__ vs __init__ (or __new__) / __del__(Python__Enter__/__Exit__vs__init__(或__new__)/__del__)
本文介绍了Python__Enter__/__Exit__vs__init__(或__new__)/__del__的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经搜索过了,但我找不出任何好的理由来使用python的__enter__/__exit__而不是__init__(或__new__?)/__del__。 我知道__enter__/__exit__旨在与with语句一起用作上下文管理器,with语句非常好。但与此对应的是,这些块中的任何代码都只在该上下文中执行。通过使用这些而不是__init__/__del__,我似乎是在与调用者创建一个他们必须使用with的隐式约定,但没有办法强制执行这样的约定,并且该约定仅通过文档(或阅读代码)进行通信。这似乎不是个好主意。

with块中使用__init__/__del__似乎得到了相同的效果。但通过使用它们而不是上下文管理方法,我的对象在其他场景中也很有用。

那么有谁能提出一个令人信服的理由,为什么我会永远想要使用上下文管理方法而不是构造函数/析构函数方法?

如果有更好的地方问这样的问题,请让我知道,但似乎没有太多关于这方面的好信息。

跟进:

这个问题基于一个不好的(但很常见的)假设,因为我总是使用with实例化一个新对象,在这种情况下,__init__/__del__非常接近__enter__/__exit__的行为(除了您无法控制何时或是否将执行__del__,这取决于垃圾回收,如果进程首先终止,它可能永远不会被调用)。但是,如果您在with语句中使用预先存在的对象,它们当然会有很大的不同。

推荐答案

您似乎忽略了几个差异:

  • 上下文管理器有机会只为您正在执行的块提供一个新对象。一些上下文管理器只返回selfhere(就像文件对象一样),但作为示例,数据库连接对象可以返回绑定到当前事务的游标对象。

  • 上下文管理器不仅会收到上下文结束的通知,还会收到退出是否由异常引起的通知。然后,它可以决定是处理该事件,还是在退出期间做出不同的反应。再次以数据库连接为例,根据存在的异常,您可以提交或中止事务。

  • __del__仅在删除对对象的所有引用时才调用。这意味着,如果您需要多个对它的引用,并且可能控制或不控制其生命周期,则不能依赖于调用它。但是,上下文管理器出口是精确定义的。

  • 上下文管理器可以重复使用,并且可以保持状态。数据库连接;您创建它一次,然后一次又一次地将其用作上下文管理器,它将使该连接保持打开状态。不需要每次都为此创建一个新对象。

    这对于线程锁很重要,例如,您必须保持状态,以便一次只能有一个线程持有锁。为此,您可以创建一个锁定对象,然后使用with lock:,这样执行该节的不同线程都可以在进入该上下文之前等待。

__enter____exit__方法形成了上下文管理器协议,只有当您真正想要管理上下文时才应该使用它们。上下文管理器的目标是简化常见的try...finallytry...except模式,而不是管理单个实例的生命周期。请参见PEP 343 – The "with" Statement

此PEP向Python语言添加了一个新的"with"语句,以便能够排除try/Finally语句的标准用法。

这篇关于Python__Enter__/__Exit__vs__init__(或__new__)/__del__的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

Leetcode 234: Palindrome LinkedList(Leetcode 234:回文链接列表)
How do I read an Excel file directly from Dropbox#39;s API using pandas.read_excel()?(如何使用PANDAS.READ_EXCEL()直接从Dropbox的API读取Excel文件?)
subprocess.Popen tries to write to nonexistent pipe(子进程。打开尝试写入不存在的管道)
I want to realize Popen-code from Windows to Linux:(我想实现从Windows到Linux的POpen-code:)
Reading stdout from a subprocess in real time(实时读取子进程中的标准输出)
How to call type safely on a random file in Python?(如何在Python中安全地调用随机文件上的类型?)