Как инициализировать базовый (супер) класс? - PullRequest
110 голосов
/ 12 сентября 2010

В 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, я нашел несколько способов сделать это.Какой стандартный способ справиться с этим?

Ответы [ 4 ]

132 голосов
/ 12 сентября 2010

Python (до версии 3) поддерживает классы "старого стиля" и нового стиля. Классы нового стиля являются производными от object и являются тем, что вы используете, и вызывают их базовый класс через 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.doit(self, foo)

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

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

36 голосов
/ 12 сентября 2010

Оба

SuperClass.__init__(self, x)

или

super(SubClass,self).__init__( x )

будет работать (я предпочитаю второй, так как он больше соответствует принципу СУХОЙ).

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

15 голосов
/ 25 октября 2017

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

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

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

Используйте объект super, чтобы обеспечить получение следующего метода (как связанного метода) впорядок разрешения метода.В Python 2 вам нужно передать имя класса и self в super для поиска ограниченного метода __init__:

 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

Обратите внимание, что __init__ может возвращать только None - он предназначен для изменения объекта на месте.

Что-то __new__

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

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

Мы обычно возвращаем экземпляр из __new__, поэтому, если вы это сделаете, вам также нужно будет вызвать __new__ вашей базы через 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 обходит немного странность супер-вызовов, вызванных __new__ статическим методом, но вам все равно нужно передать cls не__new__ метод:

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')
15 голосов
/ 12 сентября 2016

Начиная с 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

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