解释 Python 的 '__enter__' 和 '__exit__'

新手上路,请多包涵

我在某人的代码中看到了这一点。这是什么意思?

     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

原文由 zjm1126 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 568
2 个回答

使用这些神奇的方法( __enter____exit__ )允许您实现可以通过 with 语句轻松使用的对象。

这个想法是它可以很容易地构建需要执行一些“清理”代码的代码(将其视为 try-finally 块)。 这里有更多的解释

一个有用的示例可能是数据库连接对象(一旦相应的“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 - ‘with’ 语句’ 也有很好的文章。

原文由 ChristopheD 发布,翻译遵循 CC BY-SA 3.0 许可协议

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

在这个例子中,我在 open 函数的帮助下打开 myfile.txt 文件。 try/finally 块确保即使发生意外异常, myfile.txt 也会被关闭。

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

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

 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__ 方法在 with 块的开头调用, __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__ 魔法方法有了基本的了解。

原文由 N Randhawa 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题