Как инициализировать базовый (супер) класс?

В Python учтите, что у меня есть следующий код:

>>> class SuperClass(object):
    def __init__(self, x):
        self.x = x

>>> class SubClass(SuperClass):
    def __init__(self, y):
        self.y = y
        # how do I initialize the SuperClass __init__ here?

Как инициализировать SuperClass __init__ в подклассе? Я следую руководству Python, и это не распространяется на это. Когда я искал в Google, я нашел несколько способов сделать это. Каков стандартный способ справиться с этим?

Ответ 1

Python (до версии 3) поддерживает классы "старого стиля" и нового стиля. Классы нового стиля выводятся из "объекта" и используются вами, и вызывают их базовый класс через super(), например.

class X(object):
  def __init__(self, x):
    pass

  def doit(self, bar):
    pass

class Y(X):
  def __init__(self):
    super(Y, self).__init__(123)

  def doit(self, foo):
    return super(Y, self).doit(foo)

Поскольку python знает о классах старого и нового стиля, существуют разные способы вызова базового метода, поэтому вы нашли несколько способов сделать это.

Для полноты, классы старого стиля вызывают базовые методы, явно используя базовый класс, т.е.

def doit(self, foo):
  return X.foo(self, foo)

Но так как вы больше не должны использовать старомодный стиль, мне это не понравится.

Python 3 знает только о классах нового стиля (независимо от того, вы выходите из объекта или нет).

Ответ 2

И

SuperClass.__init__(self, x)

или

super(SubClass,self).__init__( x )

будет работать (я предпочитаю второй, так как он больше придерживается принципа DRY).

Смотрите здесь: http://docs.python.org/reference/datamodel.html#basic-customization

Ответ 3

Как и в случае с python 3.5.2, вы можете использовать:

class C(B):
def method(self, arg):
    super().method(arg)    # This does the same thing as:
                           # super(C, self).method(arg)

https://docs.python.org/3/library/functions.html#super

Ответ 4

Как инициализировать базовый класс (супер)?

class SuperClass(object):
    def __init__(self, x):
        self.x = x

class SubClass(SuperClass):
    def __init__(self, y):
        self.y = y

Используйте super. В Python 2:

 class SubClass(SuperClass):
      def __init__(self, y):
          super(SubClass, self).__init__('x')
          self.y = y

В Python 3 есть небольшая магия, которая делает ненужные аргументы super:

 class SubClass(SuperClass):
      def __init__(self, y):
          super().__init__('x')
          self.y = y

Жесткое кодирование такого родителя не позволяет использовать совместное множественное наследование:

 class SubClass(SuperClass):
      def __init__(self, y):
          SuperClass.__init__(self, 'x') # don't do this
          self.y = y

Что-то __new__

Существует еще один способ инициализации экземпляров - и это единственный способ для подклассов неизменяемых типов в Python. Поэтому требуется, если вы хотите подклассы str или tuple или другой неизменяемый объект.

Вы можете считать это classmethod, потому что он получает неявный аргумент класса. Но это фактически статический метод. Поэтому вам нужно явно вызвать __new__ с помощью cls.

Вам также может потребоваться позвонить в базу super, а также в базовый класс. Поэтому, если вы используете оба метода:

class SuperClass(object):
    def __new__(cls, x):
        return super(SuperClass, cls).__new__(cls)
    def __init__(self, x):
        self.x = x

class SubClass(object):
    def __new__(cls, y):
        return super(SubClass, cls).__new__(cls)

    def __init__(self, y):
        self.y = y
        super(SubClass, self).__init__('x')

Python 3 немного уменьшает странность супервызов, вызванных суперстатическим статическим методом:

class SuperClass(object):
    def __new__(cls, x):
        return super().__new__(cls)
    def __init__(self, x):
        self.x = x

class SubClass(object):
    def __new__(cls, y):
        return super().__new__(cls)
    def __init__(self, y):
        self.y = y
        super().__init__('x')