2009-12-24 3 views
5

В Python 2.x, супер принимает следующие случаиПочему python 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(instance) с типичным использованием, например, super(self).__init__(). Технически вы можете получить тип объекта из самого объекта, поэтому текущая стратегия super(ClassType, self).__init__() является излишней. Я предполагаю проблемы совместимости со старыми классами или множественное наследование, но я хотел бы услышать вашу точку зрения.
  • Почему, с другой стороны, python 3 примет (см. Understanding Python super() with __init__() methods) super().__init__()? Я вижу в этом магию, нарушая явное, лучше, чем неявный Дзен. Я бы счел более подходящим self.super().__init__().

ответ

6

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

В иерархии классов C inherits B inherits A в C.__init__ вы хотите вызвать инициализации суперкласса с C's точки зрения, и вы называете B.__init__; то в B.__init__ вы должны передать тип класса B в супер - поскольку вы хотите разрешить вызывающие суперклассы 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 (это решается в суперполе Python 3 с помощью скрытой переменной, указывающей на класс метода).

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

+0

Я предполагаю, что вы имели в виду класс B (A): и класс C (B): –

+0

Однако вы правы. Он никогда не сможет вызывать A .__ init __() из B, потому что в методе B .__ init __() self будет иметь тип C, прямой супер которого B, а не A. Итак, B .__ init __() будет вызван снова. –

+0

ах вы правы насчет опечатки, спасибо! И это становится еще сложнее в нескольких схемах наследования, я думаю, что могу найти ссылку на это. – u0b34a0f6ae

3

Я не могу дать конкретный ответ, но вы читали 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

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

Update:

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

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

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

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

+0

Я согласен, но я стараюсь, чтобы получить ответ на вопрос _while_ в то же время все большее stackoverflow информация. –

+0

@Stefano Сразу после того, как я сделал свой оригинальный пост, я начал думать об одном и том же. – David