Как переопределить конструктор класса Python со многими аргументами?
Скажем, у меня есть класс Foo, расширяющий класс Bar. И я хочу немного переопределить Foo consructor. И я не хочу даже знать, что такое подписание барных конструкторов. Есть ли способ сделать это?
Если вы не поняли, я имею в виду следующее:
class Bar:
def __init__ (self, arg1=None, arg2=None, ... argN=None):
....
class Foo (Bar):
#Here i just want add additional parameter to constructor, but don't want to know anything about Bar other parameters (arg1, arg2..., argN)
def __init__ (self, my_new_arg=None, ??? )
self.new_arg = my_new_arg
Bar.__init__(self, ??? )
Есть ли способ поставить что-то короткое и элегантное вместо??? в этом коде?
(Возможно, некоторые вариации args/kwargs)
Ответы
Ответ 1
class Parent(object):
def __init__(self, a, b):
print 'a', a
print 'b', b
class Child(Parent):
def __init__(self, c, d, *args, **kwargs):
print 'c', c
print 'd', d
super(Child, self).__init__(*args, **kwargs)
test = Child(1,2,3,4)
Вывод:
c 1
d 2
a 3
b 4
Ответ 2
Решение *args, **kwds
, представленное @Acorn, является хорошим началом (хотя я не согласен с частью ответа *args
). Этот подход представлен рядом уточнений в статье: Python Super рассмотренный супер.
Часть *args
не рекомендуется, так как она не позволяет вставлять новые классы в иерархию и исключает использование подклассами из нескольких наследований с другими классами, которые могут иметь несовместимые позиционные аргументы. Подход **kwds
работает намного лучше, потому что он не обеспечивает конкретного заказа цепочек вызовов.
Также обратите внимание: вы можете использовать именованные аргументы для разделения и удаления текущего метода с аргументами из остальных аргументов ключевого слова, прежде чем они пройдут цепочку:
class Bar(object):
def __init__(self, arg1=None, arg2=None, argN=None):
print arg1, arg2, argN
class Foo(Bar):
def __init__(self, my_new_arg=None, **kwds):
super(Foo, self).__init__(**kwds)
self.new_arg = my_new_arg
print my_new_arg
f = Foo(my_new_arg='x', arg2='y')
Наличие каждого метода для исключения аргументов, которые ему нужны, важно, потому что родительский метод, такой как object.__init__, не ожидает никаких аргументов.
Наконец, если вы собираетесь использовать super, убедитесь, что ваш самый верхний класс - это новый стиль (т.е. он наследует объект или какой-либо другой встроенный тип).