Python 带
我有五到六个资源,它们有很好的“with”处理程序,通常我会这样做:Python 带,python,Python,我有五到六个资源,它们有很好的“with”处理程序,通常我会这样做: with res1, res2, res3, res4, res5, res6: do1 do2 但是,有时不应激活其中一个或多个资源。这会导致非常难看的重复代码: with res1, res3, res4, res6: # these always acquired if res2_enabled: with res2: if res5_enabled:
with res1, res2, res3, res4, res5, res6:
do1
do2
但是,有时不应激活其中一个或多个资源。这会导致非常难看的重复代码:
with res1, res3, res4, res6: # these always acquired
if res2_enabled:
with res2:
if res5_enabled:
with res5:
do1
do2
else:
do1
do2
else if res5_enabled:
with res5:
...
一定有简单明了的方法可以做到这一点吗?您可以创建一个支持
with
语句的包装器对象,并在其中进行检查。比如:
with wrapper(res1), wrapper(res2), wrapper(res3):
...
或包装器,而不是处理所有这些:
with wrapper(res1, res2, res3):
...
您的包装器定义如下:
class wrapper(object):
def __init__(self, *objs):
...
def __enter__(self):
initialize objs here
def __exit__(self):
release objects here
如果我理解正确,您可以这样做:
from contextlib import contextmanager, nested
def enabled_resources(*resources):
return nested(*(res for res,enabled in resources if enabled))
# just for testing
@contextmanager
def test(n):
print n, "entered"
yield
resources = [(test(n), n%2) for n in range(10)]
# you want
# resources = [(res1, res1_enabled), ... ]
with enabled_resources(*resources):
# do1, do2
pass
原版海报在这里;以下是我迄今为止改进的方法: 我可以在with对象上添加(或monkey patch)bool操作符
\uuuuu nonzero\uuuu
,返回它们是否已启用。然后,当对象相互排斥时,我可以:
with res1 or res2 or res3 or res4:
...
当一个资源是可切换的,我可以创建一个空的withable,它是一个nop;威瑟似乎是个不错的名字:
class sither:
@classmethod
def __enter__(cls): pass
@classmethod
def __exit__(cls,*args): pass
...
with res1 or wither, res2 or wither:
...
我还可以使用此选项,以避免切换withable对象:
with res1 if res1enabled else wither, res2 if res2enabled else wither:
..
最后,对于我最能控制的部分,我可以将启用的检查集成到类本身中,以便在使用和未启用时,它们是nop:
with res1, res2, res3:
...
with
语句绝对是可爱的,只是看起来有点缺乏技巧。您是否考虑过在列表中添加适当的资源,使用with res\u list:
并(如有必要)在with语句中迭代res\u list
?因为我不知道你在做什么或者它是如何使用资源的,所以我不能提供一个更好的答案。。。单个资源是否作为函数参数传递?如果名字也很重要,你可以试试字典,比如res\u dict={};res_dict['res1']=;res_dict['res2']=代码>。