Python 带

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”处理程序,通常我会这样做:

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']=