在 with 语句中隐藏 post-函数调用

Hide post-function calls in with statement

我有一个函数f,returns有两个参数。在这个函数之后,我使用第一个参数。我需要第二个将东西与另一个函数粘合在一起 g。所以我的代码看起来像:

a, b = f()
# do stuff with a
g(b)

这是非常重复的,所以我想我可以使用类似 RAII 的方法。但是,因为我不知道对象什么时候会死,我的主要目标是摆脱重复的代码,所以我使用了 with 语句:

with F() as a:
    # do stuff with a

就是这样。我基本上围绕这个函数创建了一个对象 F,提供 __enter____exit__ 函数(显然还有 __init__ 函数)。

但是,我仍然想知道这是否是正确的 "Pythonic" 处理方式,因为 with 语句是用来处理异常的。特别是这个 __exit__ 函数有三个参数,我暂时不用。

编辑(进一步解释): 每当我调用 f() 时,我都需要用 b 做点什么。中间发生了什么并不重要。我表示为g(b)。而正是我隐藏在 with 声明中。因此,程序员不必在每次调用 f() 后一次又一次地键入 g(b),这可能会变得非常混乱和混乱,因为 #do stuff with a 可能会变得冗长。

对于阅读您的代码的其他人(或 6 个月后的您),上下文管理器可能会暗示资源的 creation/initialisation 和 closure/deletion,我会非常警惕重新-purposing the idiom.

您可以使用组合,而不是上下文管理器:

def func(a, b):
    # do stuff with a & optionally b

def new_f(do_stuff):
    a, b = f()
    do_stuff(a, b)
    g(b)


new_f(func)

一种稍微更 pythonic 的方法是使用 contextlib 模块。您可以使用 __enter____exit__ 功能推出自己的 class。

from contextlib import contextmanager

def g(x):
    print "printing g(..):", x

def f():
    return "CORE", "extra"

@contextmanager
def wrap():
    a, b = f()
    try:
        yield a
    except Exception as e:
        print "Exception occurred", e
    finally:
        g(b)
if __name__ == '__main__':
    with wrap() as x:
        print "printing f(..):", x
        raise Exception()

输出:

$ python temp.py
printing f(..): CORE
Exception occurred
printing g(..): extra