Ответ 1
super(SubClass, self).__init__(...)
Рассмотрите возможность использования * args и ** kw, если это поможет решить ваш ночной кошмар.
У меня есть базовый класс с большим количеством аргументов __init__
:
def BaseClass(object):
def __init__(self, a, b, c, d, e, f, ...):
self._a=a+b
self._b=b if b else a
...
Все наследующие классы должны запускать метод __init__
базового класса.
Я могу написать метод __init__()
в каждом из наследующих классов, который вызовет суперкласс __init__
, но это будет серьезное дублирование кода:
def A(BaseClass):
def __init__(self, a, b, c, d, e, f, ...):
super(A, self).__init__(a, b, c, d, e, f, ...)
def B(BaseClass):
def __init__(self, a, b, c, d, e, f, ...):
super(A, self).__init__(a, b, c, d, e, f, ...)
def C(BaseClass):
def __init__(self, a, b, c, d, e, f, ...):
super(A, self).__init__(a, b, c, d, e, f, ...)
...
Какой самый питоновский способ автоматического вызова суперкласса __init__
?
super(SubClass, self).__init__(...)
Рассмотрите возможность использования * args и ** kw, если это поможет решить ваш ночной кошмар.
Вы должны написать это явно, но, с другой стороны, если у вас много аргументов, вы, вероятно, должны использовать * args для позиционных аргументов и ** kwargs для ключевых слов args.
class SubClass(BaseClass):
def __init__(self, *args, **kwargs):
super(SubClass, self).__init__(*args, **kwargs)
# SubClass initialization code
Другим способом, который вы можете использовать, является минимизация кода в init, а затем в конце функции init вызвать другую пользовательскую функцию. Затем в подклассе вам просто нужно переопределить пользовательскую функцию
class BaseClass(object):
def __init__(self, *args, **kwargs):
# initialization code
self._a = kwargs.get('a')
...
# custom code for subclass to override
self.load()
def load():
pass
class SubClass(BaseClass)
def load():
# SubClass initialization code
...
Если производные классы не реализуют ничего, кроме того, что уже делает базовый класс __init__()
, просто опустите методы производных классов __init__()
- тогда автоматически вызывается базовый класс __init__()
.
Если, OTOH, ваши производные классы добавляют дополнительную работу в свой __init__()
, и вы не хотите, чтобы они явно вызывали свой базовый класс __init__()
, вы можете сделать это:
class BaseClass(object):
def __new__(cls, a, b, c, d, e, f, ...):
new = object.__new__(cls)
new._a=a+b
new._b=b if b else a
...
return new
class A(BaseClass):
''' no __init__() at all here '''
class B(BaseClass):
def __init__(self, a, b, c, d, e, f, ...):
''' do stuff with init params specific to B objects '''
Так как __new__()
всегда вызывается автоматически, дальнейшая работа в производных классах не требуется.
Если вы не используете что-то полезное в методах подкласса __init__()
, вам не нужно переопределять его.
def BaseClass(object):
def __init__(self, a, b, c, d, e, f, ...):
self._a=a+b
self._b=b if b else a
...
def A(BaseClass):
def some_other_method(self):
pass
def B(BaseClass):
pass
В версии 2.6 и более поздней версии для наследования init из базового класса нет суперфункции, вы можете наследовать ниже:
class NewClass():
def __init__():
BaseClass.__init__(self, *args)
Добавление реализации Pythonic. Предполагая, что вы хотите передать все атрибуты, вы можете использовать приведенный ниже код. (Можно также сохранить/удалить определенные ключи kwargs, если вы хотите подмножество).
def A(BaseClass):
def __init__(self, *args, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)
base = BaseClass(...)
new = A( **base.__dict__ )