Почему Python Super не принимает только экземпляр? - PullRequest
5 голосов
/ 24 декабря 2009

В python 2.x super принимает следующие случаи

class super(object)
 |  super(type) -> unbound super object
 |  super(type, obj) -> bound super object; requires isinstance(obj, type)
 |  super(type, type2) -> bound super object; requires issubclass(type2, type)
 |  Typical use to call a cooperative superclass method:

Насколько я вижу, super - это класс, заключающий в себе тип и (в конечном итоге) экземпляр для разрешения суперкласса класса.

Я несколько озадачен несколькими вещами:

  • почему нет также super(instance) при обычном использовании, например super(self).__init__(). Технически, вы можете получить тип объекта из самого объекта, поэтому текущая стратегия super(ClassType, self).__init__() отчасти избыточна. Я предполагаю проблемы совместимости с классами старого стиля или множественным наследованием, но я хотел бы услышать вашу точку зрения.
  • почему, с другой стороны, Python 3 будет принимать (см. Общие сведения о Python super () с помощью методов __init __ () ) super().__init__()? Я вижу в этом своего рода магию: нарушать явное лучше, чем неявное дзен. Я бы видел более уместно self.super().__init__().

Ответы [ 2 ]

6 голосов
/ 24 декабря 2009

super(ClassType, self).__init__() является не избыточным в кооперативной схеме множественного наследования - ClassType не обязательно является типом self, но классом, из которого вы хотите сделать совместный вызов __init__.

В иерархии классов C inherits B inherits A, в C.__init__ вы хотите вызвать суперкласс 'init с точки зрения C's, и вы вызываете B.__init__; затем в B.__init__ вы должны передать тип класса B в super - поскольку вы хотите разрешить вызов суперклассов B (точнее, следующего в mro после B класса C).

class A (object):
  def __init__(self):
    pass

class B (A):
  def __init__(self):
    super(B, self).__init__()

class C (B):
  def __init__(self):
    super(C, self).__init__()

если вы сейчас создадите экземпляр c = C(), вы увидите, что тип класса не является избыточным - super(self).__init__() внутри B.__init__ на самом деле не будет работать! То, что вы делаете, это то, что вы вручную указываете, к какому классу относится метод, вызывающий super (это решается в super в Python 3 скрытой переменной, указывающей на класс метода).

Две ссылки с примерами супер и множественного наследования:

3 голосов
/ 24 декабря 2009

Я не могу дать конкретный ответ, но вы читали PEP вокруг ключевого слова super? Я сделал быстрый поиск в Google, и он нашел PEP 367 и PEP 3135.

http://www.python.org/dev/peps/pep-0367/

http://www.python.org/dev/peps/pep-3135/#numbering-note

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

Обновление:

Прочитав 3135, связанные с ним электронные письма в почтовой рассылке Python и справочник по языку, он вроде как имеет смысл, почему он таков, как для Python 2 против Python 3.

http://docs.python.org/library/functions.html?highlight=super#super

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

PEP 3135 меняет все, потому что он представил и выиграл аргумент в пользу подхода DRY'er к супер.

...