Да, вы можете получить этот интерфейс.Объект, который будет введен / завершен в контексте оператора with, является разрешенным атрибутом.Таким образом, вы можете пойти дальше и определить менеджеры контекста как атрибуты вашего менеджера контекста:
from contextlib import ExitStack # pip install contextlib2
from contextlib import contextmanager
@contextmanager
def lock(name):
print("entering lock {}".format(name))
yield
print("exiting lock {}".format(name))
@contextmanager
def many(contexts):
with ExitStack() as stack:
for cm in contexts:
stack.enter_context(cm)
yield
class SuperLock(object):
def __init__(self, list_of_locks):
self.list_of_locks = list_of_locks
def __enter__(self):
# implement for entering the `with self.lock:` use case
return self
def __exit__(self, exce_type, exc_value, traceback):
pass
@property
def first_half_only(self):
return many(self.list_of_locks[:4])
@property
def second_half_only(self):
# yo dawg, we herd you like with-statements
return many(self.list_of_locks[4:])
Когда вы создаете и возвращаете новый менеджер контекста, вы можете использовать состояние из экземпляра (то есть self
).
Пример использования:
>>> list_of_locks = [lock(i) for i in range(8)]
>>> super_lock = SuperLock(list_of_locks)
>>> with super_lock.first_half_only:
... print('indented')
...
entering lock 0
entering lock 1
entering lock 2
entering lock 3
indented
exiting lock 3
exiting lock 2
exiting lock 1
exiting lock 0
Редактировать : основанный на классе эквивалент менеджера контекста генератора lock
, показанного выше
class lock(object):
def __init__(self, name):
self.name = name
def __enter__(self):
print("entering lock {}".format(self.name))
return self
def __exit__(self, exce_type, exc_value, traceback):
print("exiting lock {}".format(self.name))
# If you want to handle the exception (if any), you may use the
# return value of this method to suppress re-raising error on exit