我应该如何从with语句中返回有趣的值?

Geo*_*lly 4 python with-statement contextmanager

有没有比使用全局变量从上下文管理器获取有趣值更好的方法?

@contextmanager
def transaction():
    global successCount
    global errorCount
    try:
        yield
    except:
        storage.store.rollback()
        errorCount += 1
    else:
        storage.store.commit()
        successCount += 1
Run Code Online (Sandbox Code Playgroud)

其他可能性:

  • 单身

    有点全局...

  • 元组作为上下文管理器的参数

    使功能更加特定于问题/更少可重用

  • 将特定属性作为参数保存到上下文管理器的实例

    与元组相同的问题,但更清晰

  • 在持有值的上下文管理器的末尾引发异常.

    真的很糟糕

Jon*_*ker 7

请参阅http://docs.python.org/reference/datamodel.html#context-managers

创建一个包含成功和错误计数的类,并实现__enter____exit__方法.

  • 不是像@Ber建议的那样使用类属性,也可以通过实例化上下文管理器并在`with`语句之前将其绑定到标识符,然后在`with`中使用该标识符来解决生命周期问题.这样,上下文管理器对象将在之后仍然存在.它还需要一个`__enter __()`方法,但这只能'返回self`. (3认同)
  • 正确的。但要注意上下文管理器的生存时间。使用类属性来存储感兴趣的值,以便即使在上下文管理器超出范围后也可以检索它们。 (2认同)

Jas*_*oon 5

我仍然认为您应该创建一个类来保存错误/成功计数,正如我在上一个问题中所说的那样。我猜你有自己的类,所以只需添加如下内容:

class transaction:
    def __init__(self):
        self.errorCount = 0
        self.successCount = 0  

    def __enter__(*args):
        pass  

    def __exit__(self, type, value, traceback):
        if type:
            storage.store.rollback()
            self.errorCount += 1
        else:
            storage.store.commit()
            self.successCount += 1
Run Code Online (Sandbox Code Playgroud)

type如果调用后没有异常,则为 None contextmanager

然后您可能已经在某处使用它,它将调用contextmanager并运行您的__exit__()代码。 编辑:正如 Eli 所评论的,只有在您想要重置计数器时才创建一个新的事务实例。

t = transaction()
for q in queries:
    with t:
        t.execute(q)
Run Code Online (Sandbox Code Playgroud)