Передача параметра конструктору базового класса или использование переменной экземпляра?

Все классы, производные от определенного базового класса, должны определять атрибут под названием «путь». В смысле утиной печати я мог полагаться на определение в подклассах:

class Base:
    pass # no "path" variable here

def Sub(Base):
    def __init__(self):
        self.path = "something/"

Другой возможностью было бы использование конструктора базового класса:

class Base:
    def __init__(self, path):
        self.path = path

def Sub(Base):
    def __init__(self):
        super().__init__("something/")

Я использую Python 3.1.

Что бы вы предпочли и почему? Есть ли способ лучше?


person deamon    schedule 28.04.2010    source источник


Ответы (1)


В Python 3.0+:
я бы использовал параметр конструктора базового класса, как во втором примере. Поскольку это заставляет классы, производные от Base, предоставлять необходимое свойство пути, которое документирует тот факт, что класс имеет такое свойство и что производные классы должны его предоставлять. Без этого вы бы полагались на то, что это указано (и прочитано) где-то в строках документации вашего класса, хотя, безусловно, полезно также указать в строке документации, что означает конкретное свойство.

В Python 2.6+:
я бы не использовал ничего из вышеперечисленного; вместо этого я бы использовал:

class Base(object):
    def __init__(self,path):
        self.path=path;

class Sub(Base):
    def __init__(self):
       Base.__init__(self,"something/")

Другими словами, мне бы потребовался такой параметр в конструкторе базового класса, потому что он документирует тот факт, что все такие типы будут иметь/использовать/нуждаться в этом конкретном параметре и что этот параметр необходимо предоставить. Однако я бы не стал использовать super(), так как super несколько хрупок и опасен в Python, и я бы также сделал Base классом нового стиля, наследуя от объекта ( или из какого-то другого класса нового стиля).

person Michael Aaron Safyan    schedule 28.04.2010
comment
В super() нет ничего хрупкого. Хрупкость заключается в синтаксисе 2.x, который исправлен в 3.x (который использует OP, как показано вызовом super()), и множественном наследовании в целом. Нет никакой причины вызывать метод базового класса непосредственно в Python 3.x, синтаксис super().__init(...) никогда не бывает хуже, а часто и лучше. - person Thomas Wouters; 28.04.2010
comment
судя по использованию super, я бы предположил, что демон использует py3k - person SilentGhost; 28.04.2010
comment
@Thomas Wouters: как бы вы использовали super, если бы у вас было множественное наследование и базовые классы с разными сигнатурами конструктора? Передача всех аргументов производных классов всем базовым классам выглядит как грязный хак, полагаясь на именованные параметры и позволяя базовым классам разбираться в том, что им нужно, не намного приятнее. - person kriss; 14.04.2014