我有一个函数f
,它返回两个参数。在此功能之后,我使用第一个参数。我需要第二个将事物与另一个函数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声明中。因此,程序员不必在每次调用g(b)
后一次又一次地键入f()
,这可能会变得非常混乱和混乱,因为#do stuff with a
可能会变得冗长。
答案 0 :(得分:1)
对于其他人阅读您的代码(或者您在6个月内阅读),上下文管理器可能会暗示资源的创建/初始化和关闭/删除,而且我会非常谨慎地重新定义这些成语。 / p>
您可以使用合成,而不是上下文管理器:
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)
答案 1 :(得分:1)
稍微更加pythonic的方式是使用contextlib
模块。您可以通过__enter__
和__exit__
函数推出自己的课程。
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