Как переопределить конструктор класса Python со многими аргументами? - PullRequest
26 голосов
/ 01 декабря 2011

Скажите, у меня есть класс Foo, расширяющий класс Bar.И я хочу немного переопределить конструктор Фу.И я даже не хочу знать, что такое сигнатура конструкторов Бара.Есть ли способ сделать это?

Если вы не поняли, я имею в виду следующее:

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's other parameters (arg1, arg2..., argN)
    def __init__ (self, my_new_arg=None, ??? )
       self.new_arg = my_new_arg
       Bar.__init__(self, ??? )

Есть ли способ поставить что-то короткое и элегантное вместо ???в этом коде?(Может быть, некоторые варианты арг / кваргс)

Ответы [ 2 ]

44 голосов
/ 01 декабря 2011
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
11 голосов
/ 01 декабря 2011

Решение *args, **kwds, представленное @Acorn, является хорошим началом (хотя я не согласен с частью ответа *args).Этот подход представлен с рядом уточнений в статье: Супер Считается Супер * .

в Python. Не рекомендуется использовать *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 , убедитесь, что ваш самый верхний класс в новом стиле(т.е. он наследует от объекта или другого встроенного типа).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...