Python 运行子方法而不是父方法';s

Python 运行子方法而不是父方法';s,python,class,inheritance,Python,Class,Inheritance,我有以下类继承模式: object类B中的setup方法调用super,因此它从A调用setup方法。。。以下是方法的执行顺序: Z.setup() B.setup() A.setup (via super) B._configure B.configured.append("B") B.setup.append("A") B._configure B.configured.append("B") B.set_up.ap

我有以下类继承模式:


object类
B
中的
setup
方法调用
super
,因此它从
A
调用
setup
方法。。。以下是方法的执行顺序:

Z.setup()
  B.setup()
    A.setup (via super)
      B._configure
        B.configured.append("B")
      B.setup.append("A")
    B._configure
      B.configured.append("B")
  B.set_up.append("B")
这意味着
Z.setup
通过继承调用
B.setup
,继承调用
A.setup
通过
super
,继承调用
B.\u configure
B.setup
再次调用
B.\u configure
并在
追加后返回

希望这一点(或多或少)能说明问题

更新:这里对发生的事情做一点解释:您正在定义一个类
Z
,它有一个公共方法
设置
和一个私有方法
\u configure
。这些方法不是在
Z
类中定义的,而是在其父类
B
中定义的。但由于继承,您仍然可以调用
Z.setup
Z.\u configure

现在,
Z.setup
方法使用
B
类中的定义来工作。这将调用
super
,以便调用
A.setup
中定义的代码,同时仍处于
Z
状态,因此当调用方法
\u configure
时,将使用哪个定义?由于我们是
Z
(也就是说,
self
Z
的一个实例),将调用的方法是
Z.\u configure
,因为继承就是这样做的

再次查看代码:您正在
B
中覆盖
\u configure
方法,该方法首先在
A
中定义。由于在
B.\u configure
中没有调用
super
A.\u configure
将永远不会被调用,如果对象是从
A
继承的类的实例

TL;DR:如果
B
定义
\u configure
而不调用super,则不能从
Z
调用
A.\u configure
。这就是遗产。如果要调用
A.configure
,请不要覆盖
B
中的方法或使用
super


希望这有帮助!:)

B
中的
setup
方法调用
super
,因此它从
A
调用
setup
方法。。。以下是方法的执行顺序:

Z.setup()
  B.setup()
    A.setup (via super)
      B._configure
        B.configured.append("B")
      B.setup.append("A")
    B._configure
      B.configured.append("B")
  B.set_up.append("B")
这意味着
Z.setup
通过继承调用
B.setup
,继承调用
A.setup
通过
super
,继承调用
B.\u configure
B.setup
再次调用
B.\u configure
并在
追加后返回

希望这一点(或多或少)能说明问题

更新:这里对发生的事情做一点解释:您正在定义一个类
Z
,它有一个公共方法
设置
和一个私有方法
\u configure
。这些方法不是在
Z
类中定义的,而是在其父类
B
中定义的。但由于继承,您仍然可以调用
Z.setup
Z.\u configure

现在,
Z.setup
方法使用
B
类中的定义来工作。这将调用
super
,以便调用
A.setup
中定义的代码,同时仍处于
Z
状态,因此当调用方法
\u configure
时,将使用哪个定义?由于我们是
Z
(也就是说,
self
Z
的一个实例),将调用的方法是
Z.\u configure
,因为继承就是这样做的

再次查看代码:您正在
B
中覆盖
\u configure
方法,该方法首先在
A
中定义。由于在
B.\u configure
中没有调用
super
A.\u configure
将永远不会被调用,如果对象是从
A
继承的类的实例

TL;DR:如果
B
定义
\u configure
而不调用super,则不能从
Z
调用
A.\u configure
。这就是遗产。如果要调用
A.configure
,请不要覆盖
B
中的方法或使用
super


希望这有帮助!:)

我终于明白了,必要的魔法叫做or

解决方案非常简单,只需在配置方法的名称中使用两个下划线即可。当Python看到这种有趣的命名方法(或其他属性)时,它会悄悄地将其重命名为
\u A\u configure
,这样即使用户(无意或无意)重写了正确的方法,也会调用它

(直到现在,我还以为“两个下划线”是为Python内部保留的,谦虚地一直避免使用它们……)

固定代码:

#!/usr/bin/python

class A(object):

    def __init__(self):
        self.configured = []
        self.set_up = []

    def __configure(self):
        self.configured.append("A")

    def setup(self):
        self.__configure()
        self.set_up.append("A")

class B(A):

    def __configure(self):
        self.configured.append("B")

    def setup(self):
        super(B, self).setup()
        self.__configure()
        self.set_up.append("B")

class Z(B):
    pass

if __name__ == "__main__":
    z = Z()
    z.setup()
    print "configured: %s" % z.configured
    print "set up: %s" % z.set_up
返回所需的值

me@here:~$ ./t.py 
configured: ['A', 'B']
set up: ['A', 'B']
me@here:~$

最后我得到了它,必要的魔法叫做or

解决方案非常简单,只需在配置方法的名称中使用两个下划线即可。当Python看到这种有趣的命名方法(或其他属性)时,它会悄悄地将其重命名为
\u A\u configure
,这样即使用户(无意或无意)重写了正确的方法,也会调用它

(直到现在,我还以为“两个下划线”是为Python内部保留的,谦虚地一直避免使用它们……)

固定代码:

#!/usr/bin/python

class A(object):

    def __init__(self):
        self.configured = []
        self.set_up = []

    def __configure(self):
        self.configured.append("A")

    def setup(self):
        self.__configure()
        self.set_up.append("A")

class B(A):

    def __configure(self):
        self.configured.append("B")

    def setup(self):
        super(B, self).setup()
        self.__configure()
        self.set_up.append("B")

class Z(B):
    pass

if __name__ == "__main__":
    z = Z()
    z.setup()
    print "configured: %s" % z.configured
    print "set up: %s" % z.set_up
返回所需的值

me@here:~$ ./t.py 
configured: ['A', 'B']
set up: ['A', 'B']
me@here:~$

您的输出显示它调用了
B.\u configure
两次,而不是
A.\u configure
。这看起来与预期完全一样-通常情况下,会调用子方法,除非您使用的是
super
。您的输出显示它调用了
B.\u configure
两次,不是
A.\u configure
。这看起来像是完全按照预期工作的-一般来说,调用子方法,除非您使用
super
。我想问题是为什么
A.setup
调用
B.\u configure
而不是
A.\u configure
。因为