Meerdere overerving in python3 met verschillende handtekeningen

Ik heb drie klassen: A, Ben C.

Cerft van Aen B(in deze volgorde). De constructorhandtekeningen van Aen Bzijn verschillend. Hoe kan ik de __init__methoden van beide bovenliggende klassen aanroepen?

Mijn poging in code:

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

geeft de fout:

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

Ik heb deze brongevonden die meervoudige overerving uitlegt met verschillende reeksen argumenten, maar ze stellen voor om *argsen **kwargsom voor alle argumenten te gebruiken. Ik vind dit erg lelijk, omdat ik aan de aanroep van de constructor in de child-klasse niet kan zien wat voor soort parameters ik doorgeef aan de parent-klassen.


Antwoord 1, autoriteit 100%

Gebruik geensuper(baseclass, ...)tenzij u weet wat u doet. Het eerste argument voor super()vertelt het welke klasse het moet overslaanbij het zoeken naar de volgende methode om te gebruiken. bijv. super(A, ...)zal naar de MRO kijken, Avinden en vervolgens __init__zoeken op de volgendebasisklasse, nietAzelf. Voor Cis de MRO (C, A, B, object), dus super(A, self).__init__vindt B.__init__.

In deze gevallen wilt u geen coöperatieve overerving gebruiken, maar in plaats daarvan rechtstreeks verwijzen naar A.__init__en B.__init__. super()mag alleen worden gebruikt als de methoden die u aanroept de dezelfde handtekeninghebben of niet-ondersteunde argumenten inslikken met *argsen **vargs. In dat geval zou slechts die ene super(C, self).__init__()-aanroep nodig zijn en zou de volgende klasse in de MRO-volgorde zorgen voor het koppelen van de aanroep.

Anders gezegd: als je super()gebruikt, kun je niet weten welke klasse de volgende is in de MRO, zodat die klasse de argumenten die je eraan doorgeeft beter ondersteunt. Als dat niet het geval is, nietgebruik super().

De basis __init__methoden rechtstreeks aanroepen:

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)

Coöperatieve super()gebruiken:

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)

Other episodes