Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python3中具有不同签名的多重继承_Python_Inheritance_Python 3.x_Multiple Inheritance - Fatal编程技术网

python3中具有不同签名的多重继承

python3中具有不同签名的多重继承,python,inheritance,python-3.x,multiple-inheritance,Python,Inheritance,Python 3.x,Multiple Inheritance,我有三门课:A,B和C C继承自A和B(按此顺序)。A和B的构造函数签名不同。如何调用这两个父类的\uuuu init\uuu方法 我在代码方面的努力: class A(object): def __init__(self, a, b): super(A, self).__init__() print('Init {} with arguments {}'.format(self.__class__.__name__, (a, b))) class B(

我有三门课:
A
B
C

C
继承自
A
B
(按此顺序)。
A
B
的构造函数签名不同。如何调用这两个父类的
\uuuu init\uuu
方法

我在代码方面的努力:

class A(object):
    def __init__(self, a, b):
        super(A, self).__init__()
        print('Init {} with arguments {}'.format(self.__class__.__name__, (a, b)))

class B(object):
    def __init__(self, q):
        super(B, self).__init__()
        print('Init {} with arguments {}'.format(self.__class__.__name__, (q)))

class C(A, B):
    def __init__(self):
        super(A, self).__init__(1, 2)
        super(B, self).__init__(3)

c = C()
产生以下错误:

Traceback (most recent call last):
  File "test.py", line 16, in <module>
    c = C()
  File "test.py", line 13, in __init__
    super(A, self).__init__(1, 2)
TypeError: __init__() takes 2 positional arguments but 3 were given
回溯(最近一次呼叫最后一次):
文件“test.py”,第16行,在
c=c()
文件“test.py”,第13行,在_init中__
超级(A,自我).\u初始(1,2)
TypeError:\uuuu init\uuuuuu()接受2个位置参数,但给出了3个

我发现这解释了具有不同参数集的多重继承,但他们建议对所有参数使用
*args
**kwargs
。我认为这很难看,因为我不能从子类中的构造函数调用看到什么样的参数传递给父类。 不要使用
super(基类)
,除非你知道自己在做什么。
super()
的第一个参数告诉它在查找下一个要使用的方法时要跳过哪个类。例如,
super(A,…)
将查看MRO,找到
A
,然后开始在下一个基类上查找
\uu初始
,而不是A本身。对于
C
,MRO是
(C,A,B,object)
,因此
super(A,self)。\uuuu init\uuuu
将找到
B.\uu init\uuuu

对于这些情况,您不希望使用协作继承,而是直接引用
A.\uuu init\uuu
B.\uu init\uu
super()
仅当您调用的方法具有相同的签名或将吞下带有
*args
**vargs
的不受支持的参数时才应使用。在这种情况下,只需要一个
super(C,self)。\uuu init\uu()
调用,MRO顺序中的下一个类将负责调用上的链接

换言之:当您使用
super()
时,您无法知道MRO中的下一个类是什么,因此该类更好地支持您传递给它的参数。如果不是这样,请不要使用
super()

直接调用基本的
\uuuuu init\uuuu
方法:

class A(object):
    def __init__(self, a, b):
        print('Init {} with arguments {}'.format(self.__class__.__name__, (a, b)))

class B(object):
    def __init__(self, q):
        print('Init {} with arguments {}'.format(self.__class__.__name__, (q)))

class C(A, B):
    def __init__(self):
        # Unbound functions, so pass in self explicitly
        A.__init__(self, 1, 2)
        B.__init__(self, 3)
使用协作
super()


您使用的
super
错误,应该是
super(C,self)。
C.\uuu init\uuuu
中的
super(C,self)。由于您有不同的签名,因此您别无选择,只能处理任意的
*args,**kwargs
如果您想使用
super
super()
是在使用mixin时使用的。当您有不同的签名时,不要使用它。@NikolaiTschacher:否则,在不知道MRO中的下一个类可能是什么的情况下,您会如何请求该类的方法?但是,您总是知道要为其定义方法的当前类。我认为没有任何类作为参数的super()只会按照子类class语句中的定义走到MRO上:类A(B,C,D)的MRO是A,B,C,D。此外,我假设调用super(A,self)使用显式参数只访问超级调用中提供的类,调用方需要检查是否正确构造了任何其他父类。所以我心目中的超级(自我)只会去A班,其他什么都不会。我实际上认为A.uuu init_uuuu(self)等同于super(A,self)。此外,我还没有完全理解super(),我想…@NikolaiTschacher:如果你理解了
super()
试图解决的问题,那会有所帮助:在复杂的层次结构中调用下一个方法,使用菱形模式继承(多个子类使用的基类)。在这种情况下,使用显式的
BaseClass.\uuuuu init\uuuuu
调用很容易出错,最终您会多次调用
SharedBaseClass.\uuuuu init\uuuu
。通过使用MRO,您可以获得一个有保证的顺序,但该顺序是基于继承的动态顺序。这意味着您不应该关心下一个类是什么,只要确保其中任何一个都可以接受该调用即可。
class A(object):
    def __init__(self, a=None, b=None, *args, **kwargs):
        super().__init__(*args, **kwargs)
        print('Init {} with arguments {}'.format(self.__class__.__name__, (a, b)))

class B(object):
    def __init__(self, q=None, *args, **kwargs):
        super().__init__(*args, **kwargs)
        print('Init {} with arguments {}'.format(self.__class__.__name__, (q)))

class C(A, B):
    def __init__(self):
        super().__init__(a=1, b=2, q=3)