Проблемы с пониманием супер () при вызове нескольких родителей - PullRequest
0 голосов
/ 14 февраля 2019

Я изучал Python 3 (мой пример кода использует 3.7.2) и как правильно использовать super(), когда класс наследует более одного класса.

Я прочитал эту страницу , и эту страницу и эту статью .Я думаю, что проблема заключается в том, что ссылки SO предназначены для более старой версии Python, в то время как статья предназначена для Python 3, но это все еще сбивает с толку.

Предположим, у меня был следующий код (не беспокойтесь, если вы думаете, что отношения можно смоделировать лучше, это всего лишь пример, иллюстрирующий мою проблему):

class Weapon:

    def __init__(self, name, damage):
        self.name = name
        self.damage = damage

class Reloadable:

    def __init__(self, amount):
        self.amount = amount

class Sniper(Weapon, Reloadable):

    def __init__(self, name, damage, amount, scope_type):
        super().__init__(name, damage)
        super().__init__(self, amount)
        self.scope_type = scope_type

    def adjust_scope(self):
        print("Adjusting my scope")

Main:

gun = Sniper("Standard Sniper", 10, 20, "small")
gun.adjust_scope()

print(Sniper.__mro__)

и MRO:

(<class 'inheritnacewithsuper.Sniper'>, 
 <class 'inheritnacewithsuper.Weapon'>, 
 <class 'inheritnacewithsuper.Reloadable'>, <class 'object'>)

Код работает и вызывает нужные родительские классы, но я хочу убедиться, что при использовании Python 3.7 и super() делает ли super().__init__(name, damage) и super().__init__(self, amount) правильный способ инициализации родительских конструкторов?

В статье этого не делается, вместо этого он вызывает super() только для одного класса (RightPyramid(Square, Triangle)).

Я просто хочу убедиться, что я на правильном пути и использую надлежащие практики.

1 Ответ

0 голосов
/ 14 февраля 2019

super() требуется ваш код сотрудничает .Ваши Weapon и Reloadable классы этого не делают, поэтому вы на самом деле не хотите использовать super() здесь .Вы должны вызывать несвязанные методы непосредственно для этих базовых классов:

class Sniper(Weapon, Reloadable):
    def __init__(self, name, damage, amount, scope_type):
        Weapon.__init__(self, name, damage)
        Reloadable.__init__(self, amount)
        self.scope_type = scope_type

Без super() методы __init__ не связаны, поэтому вам необходимо явно указать self.

См. super (), считающийся супер! разработчиком ядра Python Раймондом Хеттингером (или презентация Python с одноименной конференцией для получения отличного обзора использования super() совместным образом.

Чтобы быть полностью совместными, все классы в вашей иерархии должны передавать вызовы super().<methodname>() в цепочке классов.1029 *, вам нужно либо использовать базовый класс no-op, либо обрабатывать ошибки при вызове super().__init__(), либо передавать аргументы в качестве аргументов ключевого слова, и каждый __init__() метод принимает аргументы произвольного ключевого словапередать снова:

class Weapon:
    def __init__(self, name, damage, **kwargs):
        self.name = name
        self.damage = damage
        # pass on any remaining arguments
        super().__init__(**kwargs)

class Reloadable:    
    def __init__(self, amount, **kwargs):
        self.amount = amount
        # pass on any remaining arguments
        super().__init__(**kwargs)

class Sniper(Weapon, Reloadable):    
    def __init__(self, name, damage, amount, scope_type):
        self.scope_type = scope_type
        super().__init__(name=name, damage=damage, amount=amount)

    def adjust_scope(self):
        print("Adjusting my scope")
...