为什么,在父 class 上使用 self 调用函数时,子 class 实际上是 运行 in Python
Why, when calling a function with self on the parent class, the child class is actually run in Python
我有两个抽象 class 具有以下定义:
from abc import ABC, abstractmethod
class A(ABC):
def __init__(self, lst):
self.List = lst
@abstractmethod
def __enter__(self) -> 'Component':
return self
@abstractmethod
def __exit__(self, *exc):
pass
class B(ABC):
def __init__(self, lst):
self.List = lst
@abstractmethod
def run(self):
pass
现在,我有一个 class 继承自这些:
class C(A, B):
def __init__(self, lst):
A.__init__(self, lst)
B.__init__(self, lst)
def __enter__(self) -> 'C':
self.List.append('C.__enter__')
self.run()
return self
def __exit__(self, *exc):
self.List.append('C.__exit__')
def run(self):
self.List.append('C.run')
最后,我有一个 class 继承自 C
:
class D(C):
def __init__(self, lst):
super().__init__(lst)
def __enter__(self) -> 'D':
self.List.append('D.__enter__')
super().__enter__()
return self
def __exit__(self, *exc):
super().__exit__()
self.List.append('D.__exit__')
def run(self):
self.List.append('D.run')
super().run()
现在,我的代码如下所示:
my_d = D( ['start'] )
with my_d:
pass
print(my_d)
根据我对 super()
工作原理的理解,这应该产生以下结果:
[ start,
D.__enter__,
C.__enter__,
C.run,
C.__exit__,
D.__exit__ ]
但实际发生的是:
[ start,
D.__enter__,
C.__enter__,
D.run,
C.run,
C.__exit__,
D.__exit__ ]
我没有明确调用 D.run
而 D.run
却被调用了。
这对我来说没有任何意义,除非当我在 D 中调用 super().__enter__
时,self
以某种方式认为它仍在 D
中,而实际上它在 [=20= 中].任何人都可以启发我吗?
你在调用 D.run
时调用了 C.run
:
class D(C):
def run(self):
self.List.append('D.run')
super().run() # this will add 'C.run' to self.List
与 __exit__
和 __enter__
相同。
D.run
从链 D.__enter__
-> C.__enter__
调用,现在调用 self.run()
(并且 self
有 type
D
这将调用 D.run
-> C.run
).
self
不认为是'inside D
'; self
是 类型 D
。
如果你想得到你想要的输出,你可以不覆盖 D
中的 run
;这样只会调用 C.run
。
D 中的 def run()
覆盖了 C 中的 def run()
。因此,当您在 C.__enter__
中调用 run()
时,它实际上调用了 D.run()
.
当调用 D.run()
时,super().run()
调用 C.run()
.
我第一次了解 python class 继承时同样感到困惑,但这就是它的工作原理。
我有两个抽象 class 具有以下定义:
from abc import ABC, abstractmethod
class A(ABC):
def __init__(self, lst):
self.List = lst
@abstractmethod
def __enter__(self) -> 'Component':
return self
@abstractmethod
def __exit__(self, *exc):
pass
class B(ABC):
def __init__(self, lst):
self.List = lst
@abstractmethod
def run(self):
pass
现在,我有一个 class 继承自这些:
class C(A, B):
def __init__(self, lst):
A.__init__(self, lst)
B.__init__(self, lst)
def __enter__(self) -> 'C':
self.List.append('C.__enter__')
self.run()
return self
def __exit__(self, *exc):
self.List.append('C.__exit__')
def run(self):
self.List.append('C.run')
最后,我有一个 class 继承自 C
:
class D(C):
def __init__(self, lst):
super().__init__(lst)
def __enter__(self) -> 'D':
self.List.append('D.__enter__')
super().__enter__()
return self
def __exit__(self, *exc):
super().__exit__()
self.List.append('D.__exit__')
def run(self):
self.List.append('D.run')
super().run()
现在,我的代码如下所示:
my_d = D( ['start'] )
with my_d:
pass
print(my_d)
根据我对 super()
工作原理的理解,这应该产生以下结果:
[ start,
D.__enter__,
C.__enter__,
C.run,
C.__exit__,
D.__exit__ ]
但实际发生的是:
[ start,
D.__enter__,
C.__enter__,
D.run,
C.run,
C.__exit__,
D.__exit__ ]
我没有明确调用 D.run
而 D.run
却被调用了。
这对我来说没有任何意义,除非当我在 D 中调用 super().__enter__
时,self
以某种方式认为它仍在 D
中,而实际上它在 [=20= 中].任何人都可以启发我吗?
你在调用 D.run
时调用了 C.run
:
class D(C):
def run(self):
self.List.append('D.run')
super().run() # this will add 'C.run' to self.List
与 __exit__
和 __enter__
相同。
D.run
从链 D.__enter__
-> C.__enter__
调用,现在调用 self.run()
(并且 self
有 type
D
这将调用 D.run
-> C.run
).
self
不认为是'inside D
'; self
是 类型 D
。
如果你想得到你想要的输出,你可以不覆盖 D
中的 run
;这样只会调用 C.run
。
def run()
覆盖了 C 中的 def run()
。因此,当您在 C.__enter__
中调用 run()
时,它实际上调用了 D.run()
.
当调用 D.run()
时,super().run()
调用 C.run()
.
我第一次了解 python class 继承时同样感到困惑,但这就是它的工作原理。