python多参数多重继承_带参数的多重继承

本文探讨了Python中super()函数在初始化方法调用时可能导致的问题。通过一个例子展示了当两个类互相继承并都使用super()时,如何引发错误。作者解释了错误的原因是super()会在同级类中查找方法,导致无限递归。解决方案是显式调用父类的__init__()方法,避免依赖super()。文章强调了正确理解和使用super()的重要性。
摘要由CSDN通过智能技术生成

前言:我在这里解释MRO的尝试是相当不足的。如果你有45分钟的时间,this talk来自PyCon 2015的Raymond Hettinger会做一个更好的工作。具体来说,遍历“兄弟姐妹”的想法可能会产生误导。相反,super调用只需遵循MRO(请参见help(Log))。在

尽管投了反对票,但这实际上是个好问题。在

考虑稍微修改的代码:class A(object):

def __init__(self, value):

super(A, self).__init__()

print 'A got: %s' % value

class B(object):

def __init__(self, value):

super(B, self).__init__()

print 'B got: %s' % value

class Log(A, B):

def __init__(self, a, b):

A.__init__(self, a)

B.__init__(self, b)

print 'Log'

我们可以创建A和B的实例而不会出现问题:

^{pr2}$

但是,当我们尝试创建一个Log实例时,会出现一个异常:c = Log(123,456)Traceback (most recent call last):

File "temp2.py", line 21, in

c = Log(123, 456)

File "temp2.py", line 13, in __init__

A.__init__(self, a)

File "temp2.py", line 3, in __init__

super(A, self).__init__()

TypeError: __init__() takes exactly 2 arguments (1 given)

为了弄清楚这里发生了什么,我们可以给value参数一个默认值(我使用None):class A(object):

def __init__(self, value=None):

super(A, self).__init__()

print 'A got: %s' % value

class B(object):

def __init__(self, value=None):

super(B, self).__init__()

print 'B got: %s' % value

class Log(A, B):

def __init__(self, a, b):

A.__init__(self, a)

B.__init__(self, b)

print 'Log'

现在我们同样的代码可以正常运行:c = Log(123, 456)B got: None

A got: 123

B got: 456

Log

但是输出结果可能会让您困惑:为什么要创建2b实例?或为什么指定参数默认值很重要?

好吧,考虑一下以下代码(同样,稍作修改):class A(object):

def __init__(self, value=None):

print 'A got: %s' % value

super(A, self).__init__()

class B(object):

def __init__(self, value=None):

print 'B got: %s' % value

super(B, self).__init__()

class Log(A, B):

def __init__(self, a, b):

print("Before A")

A.__init__(self, a)

print("Before B")

B.__init__(self, b)

print 'Log'

现在,当我们尝试创建c对象时:c = Log(123, 456)

我们得到:Before A

A got: 123

B got: None

Before B

B got: 456

Log

这里发生的是super(A, self).__init__()实际上在调用{}。在

这是因为super()将在父对象寻找实现该方法的人之前遍历同级。在

在本例中,它找到B的__init__方法。B的__init__方法then也查找同级,然后是父级,但是由于B没有同级(由Log类定义,该类是self的一个实例),因此B的__init__调用{},实际上什么也不做。在

换句话说(init是__init__的简写):Log.init()

A.init()

super(A, self).init() > B.init()

super(B, self).init() > object.init()

B.init()

super(B, self).init() > object.init()

A.init()中的super找到{}(而不是{})的原因是首先搜索同级。在self(Log(A,B))的上下文中,B将首先在父类之前进行检查。在

这不会像您所注意到的那样,因此super内部的B.init()不会找到A.init(),而是找到{}。同样,这是因为在Log的上下文中,B将在A之后检查,然后是父类object。在

一些阅读:

编辑:要解决此问题,可以显式调用超类__init__,而不是依赖super():class A(object):

def __init__(self, value):

object.__init__(self)

print 'First %s' % value

class B(object):

def __init__(self, value):

object.__init__(self)

print 'Second %s' % value

class Log(A, B):

def __init__(self, a, b):

A.__init__(self, a)

B.__init__(self, b)

print 'Log'

x = Log(1000, 2222)

或者,由于object.__init__()实际上什么也不做,所以您可以简单地将代码重新编写为:class A(object):

def __init__(self, value):

print 'First %s' % value

class B(object):

def __init__(self, value):

print 'Second %s' % value

class Log(A, B):

def __init__(self, a, b):

A.__init__(self, a)

B.__init__(self, b)

print 'Log'

x = Log(1000, 2222)

这两种方法都会产生你预期的结果:First 1000

Second 2222

Log

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值