Ответ 1
В качестве альтернативы вы можете написать свой код следующим образом:
with A() as a:
with B(a) as b:
# your code here
Еще одно решение, которое вы, возможно, захотите попробовать, может быть следующим:
class A:
def __init__(self):
pass
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
pass
class B(A):
def __init__(self):
super().__init__()
def __enter__(self):
super().__enter__()
return self
def __exit__(self, exc_type, exc_val, exc_tb):
super().__exit__(exc_type, exc_val, exc_tb)
Рассмотрев объяснение вашей ситуации, это может быть лучшим решением:
class Resource:
def __init__(self, dependency=None):
self.dependency = dependency
# your code here
def __enter__(self):
if self.dependency:
self.dependency.__enter__()
# your code here
return self
def __exit__(self, exc_type, exc_val, exc_tb):
# your code here
if self.dependency:
self.dependency.__exit__(exc_type, exc_val, exc_tb)
Я не уверен, правильна ли следующая реализация, но __exit__
должен правильно заботиться об исключениях. Мне несколько сложно представить, как рекурсивно связывать вызовы при правильном обращении с исключениями.
class Resource:
def __init__(self, dependency=None):
self.dependency = dependency
self.my_init()
def __enter__(self):
if self.dependency:
self.dependency.__enter__()
return self.my_enter()
def __exit__(self, exc_type, exc_val, exc_tb):
suppress = False
try:
suppress = self.my_exit(exc_type, exc_val, exc_tb):
except:
exc_type, exc_val, exc_tb = sys.exc_info()
if suppress:
exc_type = exc_val = exc_tb = None
if self.dependency:
suppress = self.dependeny.__exit__(exc_type, exc_val, exc_tb)
if not supress:
raise exc_val.with_traceback(exc_tb) from None
return suppress
def my_init(self):
pass
def my_enter(self):
pass
def my_exit(self, exc_type, exc_val, exc_tb):
pass