在 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
我有一个函数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