简体   繁体   English

为什么在父类上调用带有self的函数时,子类实际上在Python中运行

[英]Why, when calling a function with self on the parent class, the child class is actually run in Python

I have two abstract classes with the following definition: 我有两个具有以下定义的抽象类:

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

Now, I have a class that inherits from these: 现在,我有一个继承自这些类的类:

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')

Finally, I have a class that inherits from C : 最后,我有一个继承自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()

Now, my code looks like this: 现在,我的代码如下所示:

my_d = D( ['start'] )
with my_d:
    pass
print(my_d)

From my understanding of how super() works this should produce the following: 根据我对super()工作原理的了解,这应该产生以下内容:

[ start,
  D.__enter__,
  C.__enter__,
  C.run,
  C.__exit__,
  D.__exit__ ]

but what actually happens is: 但是实际发生的是:

[ start,
  D.__enter__,
  C.__enter__,
  D.run,
  C.run,
  C.__exit__,
  D.__exit__ ]

Nowhere do I explicitly call D.run and yet D.run is called. 我无处可显式调用D.run ,但D.run调用D.run

This doesn't really make sense to me unless, when I call super().__enter__ in D, self somehow thinks it's still inside D when it's actually in C . 除非我在D中调用super().__enter__ ,否则self以某种方式认为它实际上在C时仍在D ,这对我来说真的没有意义。 Can anyone enlighten me on this? 有人可以启发我吗?

you call C.run when you invoke D.run : 在调用C.run时调用D.run

class  D(C):


def run(self):
    self.List.append('D.run')
    super().run()  # this will add 'C.run' to self.List

just the same as with __exit__ and __enter__ . __exit____enter__相同。

D.run is called from the chain D.__enter__ -> C.__enter__ which now calls self.run() (and as self has type D this will call D.run -> C.run ). D.run从链称为D.__enter__ - > C.__enter__现在调用self.run()并作为self具有type D这将调用D.run - > C.run )。

self does not think it is 'inside D '; self不认为这是“ D内部”; self is of the type D . self 类型D


if you want to have your desired output you could just not override run in D ; 如果要获得所需的输出,则不能覆盖在D run that way only C.run would be called. 这样,只会C.run

def run() in D overrides the def run() in C. So when you call run() in C.__enter__ , it actually calls D.run() . def run()在d覆盖def run()所以C.当你调用run()C.__enter__ ,它实际上调用D.run()
When D.run() is called the super().run() calls C.run() . D.run()被称为super().run()调用C.run()

It was just as confusing to me the first time I learned about python class inheritance but that's just how it works. 第一次学习python类继承时,这同样让我感到困惑,但这就是它的工作方式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM