python 多重继承,继承的几个父类都需要传递参数,怎么在子类计算出父类传递的参数总和呢?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python 多重继承,继承的几个父类都需要传递参数,怎么在子类计算出父类传递的参数总和呢?相关的知识,希望对你有一定的参考价值。

比如
class A:
def __init__(num1):
self.num1 = num1
class B:
def __init__(num2):
self.num2 = num2
class C(A,B):
def num(self):
return self.num2 + self.num1

if __name__ == '__main__':
a = A(2)
b = B(5)
c = C()
print(c.num())

这样的继承,我老是出错,不知道是哪里的问题
class A:
def __init__(self,num1):
self.num1 = num1
class B:
def __init__(self,num2):
self.num2 = num2
class C(A,B):
def num(self):
return self.num2 + self.num1

if __name__ == '__main__':
a = A(2)
b = B(5)
c = C()
print(c.num())
代码这里,之前那个忘记加self了

运行你的代码:出错位置: c = C()

出错结果:TypeError: __init__() missing 1 required positional argument:  ' num1 '

先来看你的程序__main()__部分:a = A(2) 和 b = B(5) 这是类A和类B的一个实例。在python中实例变量是用于每个实例的唯一数据,这就说明你这里的传递参数2或者是5只能用在实例化的 a 或者是 b 下才有作用。  那么重点看 c = C( ) ,c是类对象C的实例化,c 只能用自身实例变量才有用,因此前面的实例 a 下的变量 num1=2 和 实例 b 下的变量 num1=5对实例c是无用的。所以,出错结果很明显了缺少传递的位置参数了。这为什么提示缺少1个位置参数呢?下面为你简单讲解一下吧。你也可以用内置方法__mro__() :查看方法或者属性的调用路径——print(类名.__mro__)

类C是多继承类A和类B的,多继承(不存在super()重写方法下),类C的实例化c是怎么工作的——对于实例c调用方法或属性过程是这样的:查找当前类C中是否存在,然后在多个父类中按照从左往右顺序查找(类A中先查找,类B中后查找),只要在这个过程中找到就退出了,后面的就不再查找了。

好吧,给你分析一下你程序的过程:类A和类B中都有__init__()同一个方法,方法相同那首先就查找呗——先查找类C(没有对__init__()进行修改,那就是跳过了),然后再去类A查找,好嘛这就找到了__init__(self, num1),找到了就退出了。所以这样一看对类C进行实例化就需要传递一个参数给num1就够了。你也可以交换继承位置class C(B, A),这样就是类C实例化需要传递一个参数给num2就够了。这样过程就清晰了。

好第三个问题来了:你类C中有两个参数呀num1和num2,而实例化又仅需要一个参数就够了,这样就肯定会产生问题了。

不信你试试给c = C(2)产生错误:AttributeError: 'C' object has no attribute 'num2'

解决方法1:既然没有属性num2就在类C中删掉就是了,然后c = C(2)就可以运行成功了。

解决方案2:类变量用于类的所有实例共享的属性和方法。因此,要想共用这两个变量num1和num2,就得让搜索的时候不要进到类A和类B中前提下,将它们变成对应的类变量就可以了。第一个前提很好实现:在类C下 定义:def __init__(self) : pass     第二个条件也比较好实现:将类A或类B的 __init__(self, num) : X.num = num   X为对应的类名。(说明:self表示类实例化对象,即self.num 表示实例变量;X表示类对象,则X.num表示类变量),这样就可以共享类A和类B的变量了。

class A:
    def __init__(self, num1):
        A.num1 = num1


class B:
    def __init__(self, num2):
        B.num2 = num2


class C(A, B):

    def __init__(self):
        pass

    def num_sum(self):
        return self.num2 + self.num1


if __name__ == '__main__':
    a = A(2)
    b = B(5)
    c = C()
    print(c.num_sum())

参考技术A

代码中:

a是 类A的实例, b是 类B的实例, c 是 类C的实例, 虽然 类C同事继承了 类A和类B, 但是"a与c" 和 "b与c" 实际上并没有关系。换句话说 那个2 不会传到类C的实例属性num1中, 那个数字3 不会传递到类C的实例属性num2 中。

而且如果这样写,类C是没有名叫num2的实例属性的。 因为python2.7 在多继承中,关于基类的寻找顺序采用的是一种广度优先算法,称之为C3的算法。 所以实际上类C的init方法和类A一样。运行的时候提示 需要一个参数, 如果你在c = C(x), 给一个数值,也会提示实例属性num2 没有定义。

个人建议,不妨试试采用 类 属性。 因为类属性 属于所有子类。 这个属性虽然归类所有,但类的所有实例都可以访问到

代码如下:

class A:
    num1 = None
    def __init__(self, num1):
        A.num1 = num1

class B:
    num2 = None
    def __init__(self, num2):
        B.num2 = num2

class C(A,B):
    
    def __init__(self):
        pass
    
    def num(self):
        return B.num2 + A.num1

if __name__ == '__main__':
    a = A(2)
    b = B(5)
    c = C()
    print "C num1"
    print C.num1
    print "C num2"
    print C.num2
    print "Summe"
    print c.num()

应该能够满足你的需求。

本回答被提问者和网友采纳

以上是关于python 多重继承,继承的几个父类都需要传递参数,怎么在子类计算出父类传递的参数总和呢?的主要内容,如果未能解决你的问题,请参考以下文章

c#中public和protect可以被子类继承下去吗

继承中子类构造函数相关问题

python 中面向对象编程的几个概念

JACA学习之继承

python 继承2个父类

python 继承2个父类