Почему супер используется так много в PySide/PyQt?

Краткая версия (tl; dr)

Я изучаю PySide, и большинство онлайн-руководств используют super для инициализации элементов пользовательского интерфейса. Является ли это важным (т.е. Более масштабируемым), или это вопрос вкуса?

Разъяснение: как я более подробно изложена в подробной версии, это еще не один общий вопрос, когда следует использовать super (это было сделано раньше). Скорее, учитывая количество обучающих программ PySide, которые используют super вместо <class>.__init__, я пытаюсь выяснить, является ли использование super стандартным в приложениях PySide? Если да, то это потому, что обстоятельства, при которых super вызывается (с разрешающим наследованием), особенно сильно зависят от использования PySide/PyQt? Или это вопрос вкуса.

Подробная версия

Я новичок в Python и в настоящее время изучаю PySide с помощью учебника Zets (http://zetcode.com/gui/pysidetutorial/firstprograms/). Второй пример в учебнике включает в себя:

from PySide import QtGui

class Example(QtGui.QWidget):
    def __init__(self):      
        super(Example, self).__init__()
        self.initUI()
    def initUI(self):
        self.setGeometry(300,300,250,150)
        self.setWindowTitle("PySide 101: Window the First!")
        self.show()

app=QtGui.QApplication(sys.argv)
ex=Example()
sys.exit(app.exec_())    

Это отлично работает, но я никогда не использовал super. Следовательно, я переписал вышеуказанный код, успешно заменив super более стандартным явным вызовом родительского класса:

QtGui.QWidget.__init__(self)

Но поскольку я ищу в Интернете учебные руководства PySide (например, http://qt-project.org/wiki/PySide-Newbie-Tutorials), все они включают вызовы super. Мой вопрос: должен ли я использовать super для PySide-скриптов?

Кажется, что super представляется наиболее полезным, когда у вас есть наследование бриллиантов, что он имеет тенденцию разрешать экземпляры множественного наследования разумным способом. Является ли super много использовать с PySide, потому что есть преобладание случаев таких бриллиантов, с которыми я столкнусь с более реалистичными сложными примерами? [Изменить: Нет: см. Мой ответ ниже.]

Почему я даже спрашиваю? Почему бы просто не использовать super и сделать с ним?

Я спрашиваю, потому что книга, которую я использую для изучения Python (Learning Python, by Lutz), тратит более 20 страниц на тему super и явно предостерегает от ее использования. Он предлагает, чтобы новые пользователи Python использовали более традиционный явный маршрут, прежде чем возиться с ним (например, см. Стр. 832 и страницы 1041-1064 Learning Python, 5th Edition). Он в основном рисует его как непитонический, тайный, редко на самом деле необходимый, новый стиль, с которым следует относиться с большой осторожностью, когда только начинаешь, и думает, что он чрезмерно используется опытными пользователями.

Кроме того, глядя на исходный код двух основных проектов на основе PySide/PyQt (Spyder и pyqtgraph), не используется super. Один (Spyder) явно сообщает вкладчикам, чтобы избежать использования его по соображениям совместимости (http://code.google.com/p/spyderlib/wiki/NoteForContributors).

Примечание. Я ссылаюсь на близкую статью ниже, но ответ там обсуждается более широко, когда вы хотели бы использовать super (когда у вас есть множественное наследование). Мой вопрос заключается в том, оправдывает ли PySide или даже требует использования super в долгосрочной перспективе, или же он более Pythonic и, лучше, по соображениям совместимости, явно указывает родительские классы? Или это вопрос вкуса?

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

Связанные темы

http://www.riverbankcomputing.com/pipermail/pyqt/2008-January/018320.html

Различные способы использования __init__ для PyQt4

Понимание Python super() с методами __init __()

Ответ 1

Хм, хороший. Но ИМО это едва ли связано с Qt/PySide.

Во-первых, как эти два разных? Если у вас есть простое наследование (возможно, не считая "mixins" ), тогда нет никакой разницы в поведении. Разница в косметике остается - вам не нужно снова называть ваш базовый класс, но вам нужно назвать тот же класс.

Различия начинаются, когда у вас есть множественное наследование. Тогда цепочка super() вызывает эту иерархию:

          A
        /   \
       X     Y
        \   /
          Z

может легко выполняться с помощью вызовов super():

          A
            \
       X --- Y
        \   
          Z

без необходимости X и Y, знающих друг друга. Это относится к концепции порядка разрешения порядка, которая позволяет использовать стиль программирования, называемый "совместное множественное наследование" в документах Python.

Если существует метод Foo, а реализации в X и Y этого метода построены на реализации A, то Z легко может полагаться как на X, так и на Y, если они не знают даже друг о друге. Это, однако, имеет важное предварительное условие: Foo имеет ту же (или, по крайней мере, [совместимую]) подпись в каждом классе, как это определено интерфейсом A, где она изначально была определена.

Метод __init__ является особенным: технически он работает точно так же с super, но! но (чаще всего) для подклассов он имеет совершенно другую подпись. Если подкласс '__init__ выглядит иначе, то super не даст вам ничего по явному базовому вызову, потому что вы все равно не можете использовать совместную многозадачность.

Примечание: Python очень нетипичен в этом отношении: в большинстве языков OO конструкторы принадлежат классу, а не экземплярам; другими словами, большинство языков полагаются на их эквиваленты __new__ и вообще не имеют __init__.

Примечание 2: Я никогда не видел никакого реального кода, который бы полагался на совместное множественное наследование. (Одиночное наследование легко делает для меня достаточное количество спагетти; -))

Кроме того, некоторые хорошие чтения:

[

Ответ 2

У меня есть то, что я считаю предварительным ответом после изучения этого, работая с PySide на прошлой неделе и отправляя по электронной почте авторов двух руководств по PySide (один из которых использует супер, а другой нет, в учебнике).

А именно, использование super в значительной степени зависит от вкуса, поскольку нет ничего плохого в создании родительских классов традиционным способом и некоторых вещей, которые следует сказать в пользу этого. Однако, по крайней мере на поверхности, использование super, похоже, упрощает будущие модификации одного кода PySide, и люди, похоже, зафиксировали это как главный фактор.

Потенциал для упрощения модификации кода происходит потому, что в PySide обычно определяют подклассы на основе объектов QtGui (например, QtQui.QMainWindow и QtGui.QWidget). Кроме того, люди склонны работать с родительскими классами настолько, чтобы было проще просто использовать super, так что вам не нужно обновлять свою функцию __init__ каждый раз, когда вы меняете родителей.

Так что не стоит использовать super, чтобы помочь разрешить случаи множественного наследования, случай, когда большинство людей соглашается, что это, вероятно, лучше всего подходит. Скорее всего, это займет меньше работы в течение __init__, если ваш родительский класс изменится в будущем.

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

Автор 1:

Я думаю, что это вопрос вкуса. Предыдущие обучающие программы (PyQt и PySide) используется init, а позже я переключился на super(). Я лично предпочитают super().

Автор 2:

Причина, по которой люди используют супер, а не. init (...) - это избегайте внесения изменений, если вы измените родительский класс, например. если вы переключаетесь с QVBoxLayout на QHBoxLayout, вам нужно только его изменить в строке определения класса, а не в методе init, так как хорошо.

Итак, у вас это есть. Не уверен, что это действительно специфично для PySide, или для написания подклассов в целом.

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