Подтвердить что ты не робот

Избегайте указания всех аргументов в подклассе

У меня есть класс:

class A(object):
    def __init__(self,a,b,c,d,e,f,g,...........,x,y,z)
        #do some init stuff

И у меня есть подкласс, которому нужен один дополнительный arg (последний W)

class B(A):
    def __init__(self.a,b,c,d,e,f,g,...........,x,y,z,W)
        A.__init__(self,a,b,c,d,e,f,g,...........,x,y,z)
        self.__W=W

Кажется глупым писать весь этот код котельной, например, передавать все аргументы из B Ctor во внутренний вызов A ctor, так как тогда каждое изменение на A ctor должно применяться к двум другим помещается в код B.

Я предполагаю, что у python есть некоторая идиома для обработки таких случаев, о которых я не знаю. Можете ли вы указать мне в правильном направлении?

Моя лучшая догадка заключается в том, чтобы иметь тип Copy-Ctor для A, а затем изменить B-код на

class B(A):
     def __init__(self,instanceOfA,W):
         A.__copy_ctor__(self,instanceOfA)
         self.__W=W

Это соответствовало бы моим потребностям, поскольку я всегда создавал подкласс, когда мне давали экземпляр класса отца, хотя я не уверен, возможно ли это...

4b9b3361

Ответ 1

Учитывая, что аргументы могут передаваться либо по имени, либо по положению, я бы code:

class B(A):
    def __init__(self, *a, **k):
      if 'W' in k:
        w = k.pop('W')
      else:
        w = a.pop()
      A.__init__(self, *a, **k)
      self._W = w

Ответ 2

Изменить: на основе предложения Мэтта и обратиться к гнибблеру с призывом к позиционно-аргументационному подходу; вы можете проверить, чтобы указать дополнительный аргумент для конкретного подкласса, похожий на ответ Alex:

class B(A):
  def __init__(self, *args, **kwargs):
    try:
      self._w = kwargs.pop('w')
    except KeyError:
      pass
    super(B,self).__init__(*args, **kwargs)

>>> b = B(1,2,w=3)
>>> b.a
1
>>> b.b
2
>>> b._w
3

Оригинальный ответ:
Такая же идея, как Matt answer, вместо этого используйте super().

Используйте super() для вызова метода суперкласса __init__(), затем продолжите инициализацию подкласса:

class A(object):
  def __init__(self, a, b):
    self.a = a
    self.b = b

class B(A):
  def __init__(self, w, *args):
    super(B,self).__init__(*args)
    self.w = w

Ответ 3

В ситуациях, когда некоторые или все аргументы, переданные в __init__, имеют значения по умолчанию, может быть полезно избежать повторения подписи __init__ в подклассах.

В этих случаях __init__ может передавать любые дополнительные аргументы другому методу, которые могут перекрывать подклассы:

class A(object):
    def __init__(self, a=1, b=2, c=3, d=4, *args, **kwargs):
        self.a = a
        self.b = b
        # …
        self._init_extra(*args, **kwargs)

    def _init_extra(self):
        """
        Subclasses can override this method to support extra
        __init__ arguments.
        """

        pass


class B(A):
    def _init_extra(self, w):
        self.w = w

Ответ 4

Вы хотите что-то вроде этого?

class A(object):
    def __init__(self, a, b, c, d, e, f, g):
        # do stuff
        print a, d, g

class B(A):
    def __init__(self, *args):
        args = list(args)
        self.__W = args.pop()
        A.__init__(self, *args)