【问题标题】:Python's 'with' statement versus 'with .. as'Python 'with' 语句与 'with .. as'
【发布时间】:2009-05-24 11:17:24
【问题描述】:

刚刚因为差异而脱发,我想知道在 Python 2.5 中真正有什么不同。

我有两个代码块(dbao.getConnection() 返回一个 MySQLdb 连接)。

conn = dbao.getConnection()
with conn:
    # Do stuff

with dbao.getConnection() as conn:
    # Do stuff

我认为这些会产生相同的效果,但显然不是因为后一个版本的 conn 对象是 Cursor。光标从何而来,是否有办法以某种方式将变量初始化和 with 语句结合起来?

【问题讨论】:

  • 第二个版本确实初始化了一个变量 conn。你有什么实际问题?有什么不同?你得到了什么错误?你能包含一些输出来显示问题吗?
  • 对不起。认为从描述中应该很清楚。 dbao.getConnection() 返回 MySQLdb 连接,因此 conn = dbao.getConnection() 导致 conn 成为 Connection 对象,而“with dbao.getConnection() as conn”导致 conn 成为 Cursor 对象。错误消息是在后一种情况下,conn 没有回滚方法,因为它是 Cursor,所以它不应该有。

标签: python syntax


【解决方案1】:

乍一看可能有点混乱,但是

with babby() as b:
    ...

等价于

b = babby()
with b:
    ...

要了解原因,以下是上下文管理器的实现方式:

class babby(object):
    def __enter__(self):
        return 'frigth'

    def __exit__(self, type, value, tb):
        pass

在第一种情况下,名称b 将绑定到从上下文管理器的__enter__ 方法返回的任何内容。这通常是上下文管理器本身(例如文件对象),但不一定是;在这种情况下,它是字符串'frigth',在您的情况下,它是数据库游标。

在第二种情况下,b 是上下文管理器对象本身。

【讨论】:

  • 在这样的时候,我希望我能给出两个答案。 :|
  • @Mikko:恕我直言,这更好——如果不是其他原因,它更详细并讨论了差异——答案应该是被接受的。
  • @martineau:因为我们在评论旧的 cmets!是的,这个答案更详细并讨论了差异。它提供了更多的背景信息,从这个意义上说它更好。但作为答案,它是颠倒的。接受的答案设法回答(第一)两行中的特定问题。有了这个,我需要在收到问题的答案之前通读示例案例等。一个完美的答案将接受的答案作为第一段,然后是本段。背景信息很好,但有时只是得到答案也令人耳目一新。
【解决方案2】:

一般而言,with 语句的 as 部分分配的值将是 __enter__ method of the context manager 返回的任何值。

【讨论】:

  • 怀疑这一点。感谢您的确认!
【解决方案3】:

with 语句用于确保事务正确启动和停止。

对于python中的数据库连接,我认为很自然的做法是在with语句的开头创建一个游标,然后在它的结尾提交或回滚事务。

从 with 语句的角度来看,您给出的两个块是相同的。您也可以将 as 添加到第一个并获取光标。

您需要检查与支持在您使用的对象中是如何实现的。

http://docs.python.org/whatsnew/2.5.html#pep-343-the-with-statement

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-11
    • 2011-02-13
    • 2015-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多