解释Python的“enter”和“exit”

2024-04-19 12:54:21 发布

您现在位置:Python中文网/ 问答频道 /正文

我在别人的密码里看到的。这是什么意思?

    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

Tags: fromself密码closestreamreturnvaluedef
3条回答

我发现很难通过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)
Enter the runtime context related to this object. The with statement will bind this method’s return value to the target(s) specified in the as clause of the statement, if any.

object.__exit__(self, exc_type, exc_value, traceback)
Exit the runtime context related to this object. The parameters describe the exception that caused the context to be exited. If the context was exited without an exception, all three arguments will be None.

If an exception is supplied, and the method wishes to suppress the exception (i.e., prevent it from being propagated), it should return a true value. Otherwise, the exception will be processed normally upon exit from this method.

Note that __exit__() methods should not reraise the passed-in exception; this is the caller’s responsibility.

我希望对__exit__方法参数有一个清晰的描述。这是缺乏的,但我们可以推断。。。

假设exc_type是异常的类。

它说您不应该重新引发传入异常。这向我们表明,其中一个参数可能是一个实际的异常实例……或者您应该自己从类型和值实例化它?

我们可以通过看这篇文章来回答:
http://effbot.org/zone/python-with-statement.htm

For example, the following __exit__ method swallows any TypeError, but lets all other exceptions through:

def __exit__(self, type, value, traceback):
    return isinstance(value, TypeError)

……很明显value是一个异常实例。

假设traceback是一个Pythontraceback对象。

如果您知道什么是上下文管理器,那么您就不需要再了解__enter____exit__魔术方法。让我们看一个非常简单的例子。

在本例中,我在open函数的帮助下打开myfile.txttry/finally块确保即使发生意外异常,也将关闭myfile.txt

fp=open(r"C:\Users\SharpEl\Desktop\myfile.txt")
try:
    for line in fp:
        print(line)
finally:
    fp.close()

现在我用打开同一个文件,语句是:

with open(r"C:\Users\SharpEl\Desktop\myfile.txt") as fp:
    for line in fp:
        print(line) 

如果您查看代码,我没有关闭文件&;没有try/finally块。因为with语句会自动关闭myfile.txt。您甚至可以通过调用print(fp.closed)属性来检查它——该属性返回True

这是因为open函数返回的文件对象(在我的示例中是fp)有两个内置方法__enter____exit__。它也被称为上下文管理器。__enter__方法在带有块的开头调用,而__exit__方法在结尾调用。注意:with语句仅适用于支持上下文更改协议的对象,即它们具有__enter____exit__方法。实现这两种方法的类称为上下文管理器类。

现在让我们定义自己的上下文管理器类。

 class Log:
    def __init__(self,filename):
        self.filename=filename
        self.fp=None    
    def logging(self,text):
        self.fp.write(text+'\n')
    def __enter__(self):
        print("__enter__")
        self.fp=open(self.filename,"a+")
        return self    
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("__exit__")
        self.fp.close()

with Log(r"C:\Users\SharpEl\Desktop\myfile.txt") as logfile:
    print("Main")
    logfile.logging("Test1")
    logfile.logging("Test2")

我希望现在您对__enter____exit__魔术方法都有了基本的了解。

使用这些神奇的方法(__enter____exit__)可以实现可以很容易地与with语句一起使用的对象。

其思想是,它使构建需要执行一些“清除”代码的代码变得容易(将其视为try-finally块)。Some more explanation here

一个有用的示例可能是数据库连接对象(当相应的“with”语句超出范围时,该对象将自动关闭连接):

class DatabaseConnection(object):

    def __enter__(self):
        # make a database connection and return it
        ...
        return self.dbconn

    def __exit__(self, exc_type, exc_val, exc_tb):
        # make sure the dbconnection gets closed
        self.dbconn.close()
        ...

如上所述,将此对象与with语句一起使用(如果您使用的是Python 2.5,则可能需要在文件顶部执行from __future__ import with_statement)。

with DatabaseConnection() as mydbconn:
    # do stuff

PEP343 -- The 'with' statement'写得也不错。

相关问题 更多 >