不带“as”关键字的“with”语句的含义

2024-04-24 04:42:27 发布

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

我熟悉使用python的with语句来确保在抛出异常时完成对象。这通常看起来像

with file.open('myfile.txt') as f:
    do stuff...

它是

f = file.open('myfile.txt'):
try:
    do stuff...
finally:
    f.close()

或者类可能出现的任何其他终结例程。

我最近遇到一段处理OpenGL的代码,它展示了以下内容:

with self.shader:
    (Many OpenGL commands)

请注意,没有任何as关键字。这是否表示类的__enter____exit__方法仍将被调用,但对象从未在块中显式使用(即,它通过全局或隐式引用工作)?或者还有什么其他的意思在逃避我?


Tags: 对象txtcloseaswith语句openmyfile
1条回答
网友
1楼 · 发布于 2024-04-24 04:42:27

上下文管理器可以选择返回一个对象,该对象将被分配给由as命名的标识符。它是由as分配的__enter__方法返回的对象,不一定是上下文管理器本身。

使用as <identifier>有助于创建新的对象,就像open()调用一样,但并非所有上下文管理器都是为上下文创建的。例如,它们可以重用并且已经被创建。

建立数据库连接。您只需创建一次数据库连接,但许多数据库适配器允许您将该连接用作上下文管理器;输入上下文并启动事务,退出该事务,然后该事务将被提交(成功时)或回滚(出现异常时):

with db_connection:
    # do something to the database

这里不需要创建新的对象,上下文是用db_connection.__enter__()输入的,用db_connection.__exit__()退出的,但是我们已经有了对连接对象的引用。

现在,可能是连接对象在您输入时生成一个游标对象。现在,在本地名称中指定游标对象是有意义的:

with db_connection as cursor:
    # use cursor to make changes to the database

这里仍然没有调用db_connection,它以前已经存在,我们已经有了对它的引用。但是无论产生什么db_connection.__enter__()现在都被分配给cursor并且可以从那里开始使用。

这就是文件对象的情况;open()返回一个文件对象,而fileobject.__enter__()返回文件对象本身,因此可以在with语句中使用open()调用,并在一个步骤(而不是两个步骤)中为新创建的对象分配引用。没有这个小把戏,你就得用:

f = open('myfile.txt')
with f:
    # use `f` in the block

将所有这些应用于着色器示例;您已经有了对self.shader的引用。很可能self.shader.__enter__()再次返回对self.shader的引用,但是既然已经有了一个完全可用的引用,为什么还要为此创建一个新的本地引用?

相关问题 更多 >