Alternativ können Sie Ihren Code wie so schreiben:
with A() as a:
with B(a) as b:
# your code here
Eine andere Lösung, die Sie vielleicht ausprobieren möchten dies sein könnte:
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)
Nach Prüfung der Erklärung Ihrer Situation, könnte dies sein eine bessere Lösung:
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)
Ich bin mir nicht sicher, ob die folgende Implementierung ist korrekt, aber __exit__
muss sorgfältig auf Ausnahmen achten. Es ist etwas schwierig für mich, sich vorzustellen, wie man die Aufrufe rekursiv kettet, während Ausnahmen gut behandelt werden.
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
Interessant. Das könnte auch funktionieren. Der Nachteil davon ist, dass der Benutzer unserer Klasse "B" die Instanz von "A" erstellen und an uns weitergeben muss. Außerdem würde es immer komplizierter werden, wenn die Kette der Anforderungen mehr als eine Ebene tief ist. Aber gute Idee für einfache Fälle. Vielen Dank. – Sahand
@NoctisSkytower Ihr klassenbasierter Ansatz ist nur dann praktikabel, wenn es wirklich sinnvoll ist, dass B eine Unterklasse von A. IMO ist. Diese Beziehung sollte nicht strikt erstellt werden, um sie als Kontextmanager einfacher zu verschachteln, da sie gegen die " IS-A "Prinzip der OO-Programmierung. – dano
Ich stimme @dano zu. Wenn es logisch sinnvoll ist, dass "B" eine Unterklasse von "A" ist, ist dies eine sehr gute Lösung. Mein Beispiel oben ist zu stark vereinfacht. In meinem tatsächlichen Anwendungsfall ist es dieselbe Klasse, die rekursiv Referenzen auf Instanzen von sich selbst hat (etwa wie eine verkettete Liste), und daher müssen sie alle rekursiv freigegeben werden. Die Vererbungsidee würde dort nicht funktionieren. – Sahand