Подтвердить что ты не робот

Как многократное наследование работает с аргументами super() и разными __init __()?

Я просто погружаюсь в некоторые более продвинутые темы python (ну, по крайней мере, продвинулся ко мне). Теперь я читаю о множественном наследовании и о том, как вы можете использовать super(). Я более или менее понимаю, как используется суперфункция, но (1) Что не так с этим просто:?:

class First(object):
    def __init__(self):
        print "first"

class Second(object):
    def __init__(self):
        print "second"

class Third(First, Second):
    def __init__(self):
        First.__init__(self)
        Second.__init__(self)
        print "that it"

В супер(), Статья Андрея Кучлинга о бородах на питоне говорит:

использование super() также будет правильным, если класс Derived наследует из нескольких базовых классов, а некоторые или все из них имеют initМетоды

Итак, я переписал приведенный выше пример следующим образом:

class First(object):
    def __init__(self):
        print "first"

class Second(object):
    def __init__(self):
        print "second"

class Third(First, Second):
    def __init__(self):
        super(Third, self).__init__(self)
        print "that it"

Тем не менее, он запускает только первый init, который находится в First. (2) Можно использовать super() для запуска как init из First, так и Second, и если да, то как? Запуск super(Third, self).__init__(self) дважды запускается сначала. init() дважды.

Чтобы добавить еще одну путаницу. Что делать, если функции унаследованных классов init() принимают разные аргументы. Например, что, если бы у меня было что-то вроде этого:

class First(object):
    def __init__(self, x):
        print "first"

class Second(object):
    def __init__(self, y, z):
        print "second"

class Third(First, Second):
    def __init__(self, x, y, z):
        First.__init__(self, x)
        Second.__init__(self, y, z)
        print "that it"

(3) Как я могу предоставить соответствующие аргументы для различных функций инициализации наследуемых классов с помощью функции super()?

Все советы приветствуются!

пс. Поскольку у меня есть несколько вопросов, я сделал их жирным шрифтом и пронумеровал их.

4b9b3361

Ответ 1

Для вопроса 2 вам нужно вызвать super в каждом классе:

class First(object):
    def __init__(self):
        super(First, self).__init__()
        print "first"

class Second(object):
    def __init__(self):
        super(Second, self).__init__()
        print "second"

class Third(First, Second):
    def __init__(self):
        super(Third, self).__init__()
        print "that it"

Для вопроса 3 это невозможно сделать, ваш метод должен иметь одну и ту же подпись. Но вы можете просто игнорировать некоторые параметры в родительских кланах или использовать аргументы ключевых слов.

Ответ 2

1) Нет ничего плохого в том, что вы сделали в 1, если вы хотите использовать атрибуты из базового класса, тогда вам нужно вызвать базовый класс init() или даже если ur, используя методы из базового класса, который использует атрибуты своего собственного класса, тогда вы должны вызвать baseclass init()

2) Вы не можете использовать super для запуска init с первого и второго, потому что python использует MRO (порядок разрешения метода)

см. следующий код, это иерархия алмазов

class A(object): 
    def __init__(self):
        self.a = 'a'
        print self.a

class B(A):
    def __init__(self):
        self.b = 'b'
        print self.b

class C(A):
    def __init__(self):
        self.c = 'c'
        print self.c

class D(B,C):
    def __init__(self):
        self.d = 'd'
        print self.d
        super(D, self).__init__()

d = D()
print D.mro()

Он печатает:

d
b
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>]

MRO питона будет D, B, C, A

если B не имеет метода init, он идет для C.

3) Вы не можете использовать все методы, чтобы иметь одну и ту же подпись.