Alternatywnie, można napisać kod tak:
with A() as a:
with B(a) as b:
# your code here
Innym rozwiązaniem może chcesz spróbować może być to:
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)
Po rozpatrzeniu wyjaśnienie swojej sytuacji, to może być lepsze rozwiązanie:
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)
Nie jestem pewien, czy następująca implementacja jest poprawny, ale __exit__
musi odpowiednio dbać o wyjątki. Trudno mi sobie wyobrazić, jak rekurencyjnie łączyć wywołania przy prawidłowej obsłudze wyjątków.
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
interesujące. To też może działać. Wadą tego jest to, że użytkownik naszej klasy 'B' będzie musiał stworzyć instancję' A' i przekazać ją nam. Co więcej, byłoby to jeszcze bardziej skomplikowane, gdyby łańcuch wymagań był głębszy niż jeden poziom. Ale dobry pomysł na proste przypadki. Dziękuję Ci. – Sahand
@NoctisSkytower Twoje podejście oparte na klasach jest opłacalne tylko wtedy, gdy naprawdę ma sens, by B było pod-klasą A. IMO, że relacja nie powinna być tworzona ściśle, aby zagnieżdżanie jej było łatwiejsze, ponieważ narusza " IS-A "zasada programowania OO. – dano
Zgadzam się z @dano. Jeśli logiczne jest, że 'B' jest podklasą' A', jest to bardzo dobre rozwiązanie. Mój przykład powyżej jest uproszczony. W moim przypadku użycia, to ta sama klasa, która odwołuje się do samych rekurencyjnie wystąpień (trochę jak lista połączona), a więc wszystkie muszą być wydawane rekursywnie. Pomysł dziedziczenia nie zadziałałby tam. – Sahand