我在某人的代码里看到了这个。这是什么意思?
def __enter__(self):
return self
def __exit__(self, type, value, tb):
self.stream.close()
字符串
这里是完整的代码。
from __future__ import with_statement#for python2.5
class a(object):
def __enter__(self):
print 'sss'
return 'sss111'
def __exit__(self ,type, value, traceback):
print 'ok'
return False
with a() as s:
print s
print s
型
7条答案
按热度按时间zpqajqem1#
使用这些神奇的方法(
__enter__
,__exit__
),您可以实现可以轻松使用with
语句的对象。这个想法是,它使构建需要执行一些“清理”代码的代码变得容易(将其视为
try-finally
块)。一个有用的例子可能是数据库连接对象(一旦相应的“with”语句超出范围,它就会自动关闭连接):
字符串
如上所述,将此对象与
with
语句一起使用(如果使用的是Python 2.5,则可能需要在文件的顶部执行from __future__ import with_statement
)。型
PEP343 -- The 'with' statement'也有不错的文章。
nxagd54h2#
如果你知道什么是上下文管理器,那么你就不需要更多的东西来理解
__enter__
和__exit__
魔术方法了。让我们看一个非常简单的例子。在这个例子中,我使用open函数打开myfile.txt文件。try/finally块确保即使出现意外异常,myfile.txt也会关闭。
字符串
现在我用with语句打开同一个文件:
型
如果你看一下代码,我没有关闭文件,也没有try/finally块。因为with语句会自动关闭myfile.txt。你甚至可以通过调用
print(fp.closed)
属性来检查它--它返回True
。这是因为open函数返回的文件对象(在我的例子中是fp)有两个内置方法
__enter__
和__exit__
。它也被称为上下文管理器。__enter__
方法在with块的开头被调用,__exit__
方法在结尾被调用。注意事项:with语句只适用于支持上下文管理协议的对象(即它们具有
__enter__
和__exit__
方法)。实现这两种方法的类称为上下文管理器类。现在让我们定义我们自己的context manager类。
型
我希望现在你对
__enter__
和__exit__
魔术方法都有了基本的了解。bis0qfac3#
我发现通过Google查找
__enter__
和__exit__
方法的python文档非常困难,所以为了帮助其他人,以下链接是:https://docs.python.org/2/reference/datamodel.html#with-statement-context-managers
https://docs.python.org/3/reference/datamodel.html#with-statement-context-managers
(两个版本的详细信息相同)
object.__enter__(self)
个输入与此对象相关的运行时上下文。
with
语句会将此方法的返回值绑定到在语句的as子句中指定的目标(如果有)。object.__exit__(self, exc_type, exc_value, traceback)
个退出与此对象相关的运行时上下文。参数描述了导致上下文退出的异常。如果上下文在没有异常的情况下退出,则所有三个参数都将是
None
。如果提供了一个异常,并且该方法希望抑制该异常(即,阻止其传播),则它应该返回一个true值。否则,在退出该方法时,将正常处理该异常。
请注意,
__exit__()
方法不应重新引发传入的异常;这是调用方的责任。我希望对
__exit__
方法的参数有一个清晰的描述。这是缺乏的,但我们可以推导出它们...假定
exc_type
是异常的类。它说你不应该重新引发传入的异常,这意味着其中一个参数可能是一个实际的Exception示例......或者你应该自己从类型和值中示例化它?
我们可以通过看这篇文章来回答:
http://effbot.org/zone/python-with-statement.htm
例如,下列
__exit__
方法会吞下任何TypeError,但会让所有其他例外状况通过:字符串
......所以
value
显然是一个异常示例。而且
traceback
大概是Python的traceback对象。请注意,此处还有更多文档:
https://docs.python.org/3/library/stdtypes.html#context-manager-types
...他们对
__enter__
和__exit__
方法有更详细的解释,特别是__exit__
应该返回一个布尔值(尽管真或假都可以,例如隐式的None
返回将给予传播异常的默认行为)。uqxowvwt4#
除了上面对EJB调用顺序的回答之外,
字符串
生成输出:
型
提醒一下:当使用语法
with MyClass() as my_handler
时,变量my_handler获取__enter__()
返回的值,在上面的情况下为None
!对于这样的使用,需要定义返回值,例如:型
amrnrhlw5#
试着加上我的答案(我对学习的想法):
__enter__
和[__exit__]
都是在进入和退出“the with statement”(PEP 343)的主体时调用的方法,两者的实现都称为上下文管理器。with语句的目的是隐藏try finally子句的流控制,并使代码不可理解。
with语句的语法是:
字符串
其翻译为(如PEP 343中所述):
型
试试代码:
型
现在手动尝试(遵循translate语法):
型
服务器端的结果和以前一样
对不起,我的英语不好,我的解释不清楚,谢谢你。
a9wyjsp76#
这被称为上下文管理器,我只是想补充一下,其他编程语言也存在类似的方法。比较它们有助于理解Python中的上下文管理器。基本上,当我们处理一些资源时,会使用上下文管理器。(文件、网络、数据库)需要初始化,并且在某些时候,在Java 7及更高版本中,我们有自动资源管理,其形式为:
字符串
请注意,Session需要实现
AutoClosable
或它的一个(许多)子接口。在**C#**中,我们有using语句来管理资源,其形式如下:
型
其中
Session
应该实现IDisposable
。在python中,我们使用的类应该实现
__enter__
和__exit__
。所以它的形式是:型
正如其他人指出的,你可以在所有的语言中使用try/finally语句来实现相同的机制,这只是语法糖。
q3aa05257#
当执行进入with语句的上下文并且是时候获取资源时,Python调用
__enter__
。当执行再次离开上下文时,Python调用__exit__
来释放资源让我们考虑一下Python中的上下文管理器和“with”语句。(或接口),这样它就可以与with语句一起使用。基本上,您需要做的就是添加enter和exit如果你想让一个对象作为一个上下文管理器,Python会在资源管理周期的适当时间调用这两个方法。
让我们来看看这在实际中是什么样子的。下面是open()上下文管理器的简单实现:
字符串
我们的ManagedFile类遵循上下文管理器协议,现在支持with语句。
型
当执行进入with语句的上下文,需要获取资源时,Python会调用enter。当执行再次离开上下文时,Python会调用exit来释放资源。
编写一个基于类的上下文管理器并不是支持Python中with语句的唯一方法。标准库中的contextlib实用程序模块提供了一些构建在基本上下文管理器协议之上的抽象。如果您的用例与contextlib提供的内容匹配,这可以让您的生活更轻松。