Ответ 1
Конечно, один предпочитает подход 1 приблизиться к 2 (поскольку подход 2 отводит базу к интерфейсу тега, а не выполняет абстрактную функциональность). Но подход 1 сам по себе не отвечает вашей цели - не дать разработчику подтипа забыть правильно реализовать вызов super(), гарантируя инициализацию.
вы можете захотеть просмотреть шаблон "Factory", чтобы облегчить возможность реализации инициализации подтипов. Рассмотрим:
class AbstractClass(object):
'''Abstract base class template, implementing factory pattern through
use of the __new__() initializer. Factory method supports trivial,
argumented, & keyword argument constructors of arbitrary length.'''
__slots__ = ["baseProperty"]
'''Slots define [template] abstract class attributes. No instance
__dict__ will be present unless subclasses create it through
implicit attribute definition in __init__() '''
def __new__(cls, *args, **kwargs):
'''Factory method for base/subtype creation. Simply creates an
(new-style class) object instance and sets a base property. '''
instance = object.__new__(cls)
instance.baseProperty = "Thingee"
return instance
Этот базовый класс может быть расширен более тривиально, чем в подходе 1, используя только три (3) строки кодовой санкции, следующим образом:
class Sub(AbstractClass):
'''Subtype template implements AbstractClass base type and adds
its own 'foo' attribute. Note (though poor style, that __slots__
and __dict__ style attributes may be mixed.'''
def __init__(self):
'''Subtype initializer. Sets 'foo' attribute. '''
self.foo = "bar"
Обратите внимание, что хотя мы не называем конструктор суперкласса, baseProperty будет инициализирован:
Python 2.6.1 (r261:67515, Jun 24 2010, 21:47:49)
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from TestFactory import *
>>> s = Sub()
>>> s.foo
'bar'
>>> s.baseProperty
'Thingee'
>>>
Как указывает его комментарий, базовому классу AbstractClass не нужно использовать слоты, он может так же легко "неявно" определять атрибуты, устанавливая их в своем новом() инициализаторе, Например:
instance.otherBaseProperty = "Thingee2"
будет работать нормально. Также обратите внимание, что инициализатор базового класса поддерживает тривиальные инициализаторы (no-arg) в своих подтипах, а также инициализаторы с переменной поправкой и переменной длины. Я рекомендую всегда использовать эту форму, поскольку она не накладывает синтаксиса в случае простейшего (тривиального конструктора), но позволяет использовать более сложную функциональность, не требуя обслуживания.