为什么在PySide/PyQt中超级使用了这么多?

eri*_*ric 13 python pyqt super pyside

短版(tl; dr)

我正在学习PySide,大多数在线教程都super用来初始化UI元素.这是重要的(即,更具可扩展性),还是品味问题?

澄清:当我在详细版本中更清楚时,这不是另一个通知线程,询问何时使用super(这已经在之前完成).相反,考虑到使用PySide教程的数量super,而不是<class>.__init__,我想如果用弄清楚super是PySide应用程序的标准?如果是这样,是因为super在使用PySide/PyQt时需要特别提到的(涉及解决继承问题)?或者这是品味问题.

详细版本

我是Python的新手,目前正在使用Zets教程学习PySide(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_())    
Run Code Online (Sandbox Code Playgroud)

这工作正常,但我从未使用过super.因此,我重写了上面的代码,成功地替换super了父类的更标准的显式调用:

QtGui.QWidget.__init__(self)
Run Code Online (Sandbox Code Playgroud)

但是,当我在网上搜索PySide教程时(例如,http://qt-project.org/wiki/PySide-Newbie-Tutorials ),它们包括调用super.我的问题是:我应该super用于PySide脚本吗?

看来,super当你有继承的钻石,它倾向于解决多重继承的情况下,以合理的方式似乎是最有帮助的.是否super与PySide一起使用,因为这些钻石的案例占优势,我会面对更现实的复杂例子?[编辑:否:请参阅下面的答案.]

我为什么要问?为什么不直接使用super并完成它?

我在问,因为我用来学习Python的书(学习Python,由Lutz撰写)花了20多页关于这个主题super,并明确告诫不要使用它.他建议新的Python用户在使用它之前采用更传统,更明确的路线(例如,参见第832页,学习Python的第1041-1064页,第5版).他基本上将它描绘成一种非剧性的,神秘的,很少需要的新风格,刚开始时你应该非常谨慎地对待它,并认为它被有经验的用户过度使用.

此外,查看两个主要的PySide/PyQt项目(Spyder和pyqtgraph)的源代码,两者都没有使用super.One(Spyder)明确告诉贡献者出于兼容性原因而避免使用它(http://code.google.com/p/spyderlib/wiki/NoteForContributors).

注意我链接到下面一个密切相关的帖子,但是当你想要使用时super(当你有多个继承时),那里的答案会更一般地讨论.我的问题是PySide脚本是否证明甚至要求super长期使用,或者它是否更具Pythonic,并且出于兼容性原因更好地明确命名父类?还是味道问题?

如果它不受欢迎(正如我的初学者所说),为什么它在针对初学者的PySide教程中如此普遍?如果它有任何区别,那么编写这些教程的人似乎是经验丰富的Java程序员,或者迎合这些程序员.我不是.

相关话题

http://www.riverbankcomputing.com/pipermail/pyqt/20​​08-January/018320.html

使用__init__ for PyQt4的不同方法

使用__init __()方法理解Python super()

Kos*_*Kos 8

嗯,很好.但IMO与Qt/PySide几乎没有关系.

首先,这两者有何不同?如果你有简单的继承(也许不算"mixins"),那么行为就没有区别了.化妆品差异仍然存在 - 您不需要再次命名基类 - 但您必须命名同一个类.

当您有多个继承时,差异就会开始.然后是super()这个层次结构的一系列调用:

          A
        /   \
       X     Y
        \   /
          Z
Run Code Online (Sandbox Code Playgroud)

通过super()电话可以很容易地进行:

          A
            \
       X --- Y
        \   
          Z
Run Code Online (Sandbox Code Playgroud)

不需要X和Y相互了解.这涉及方法解析顺序的概念,它允许在Python文档中称为"协作多重继承"的编程风格.

如果该方法的FooX和Y中的方法和实现基于A的实现构建,那么Z很容易依赖于X和Y,而他们甚至不知道彼此.然而,这有一个重要的前提条件:Foo在每个类中具有相同(或至少[兼容])签名,如A最初定义的接口所指定的那样.

__init__方法是特殊的:在技术上它正好与相同的方式工作super,但!但是(通常情况下),对于子类,它具有完全不同的签名.如果子类' __init__看起来不同,那么super就不会给你任何超过显式基本调用的东西,因为你无论如何都无法使用协作式多任务处理.

注意:Python在这方面非常不典型:在大多数OO语言中,构造函数属于类,而不是实例; 换句话说,大多数语言都依赖于它们的等价物__new__而根本没有__init__.

注2:我从未见过任何依赖合作多重继承的真实代码.(单遗传很容易为我制作足够的意大利面;-))

还有一些好的阅读:

[

  • 我猜这个普遍使用的事实是因为一旦你决定使用`super`而不是`<class> .__ init__`这一事实,它只是更好的风格来保持一致,而不是在所有可能的变化.您的第一个相关主题中描述的"混淆"清楚地证明了这一点. (2认同)

eri*_*ric 6

在研究了这个问题之后我得到了临时答案,上周与PySide合作,并通过电子邮件发送了两篇关于PySide的教程的作者(其中一篇使用了super,另一篇没有,在教程中).

也就是说,使用super很大程度上是一种品味问题,因为以传统方式实例化父类没有任何问题,并且有些事情可以说是有利于它.然而,至少在表面上,使用QtGui似乎简化了对一个人的PySide代码的未来修改,人们似乎已经把它作为最重要的因素.

简化代码修改的可能性是因为在PySide中,通常基于QtGui对象(例如,QtQui.QMainWindowQtGui.QWidget)定义子类.此外,人们倾向于使用他们的父类足够多,以便使用起来更容易super,这样您每次更换父母时都不必更新__init__功能.

所以这不是super用来帮助解决多重继承案例的问题,大多数人都认为它可能是最适合的.相反,如果您的父类将来发生变化,则需要在__init__中减少工作量.

以下是每位作者的回复,他们都写了我认为好的PySide教程:

作者1:

我认为这是一个品味问题.早期教程(PyQt和PySide)使用.init和后来我切换到super().我个人更喜欢super().

作者2:

人们使用super代替的原因.init(...)是为了避免在更改父类的内容时进行更改,例如,如果从QVBoxLayout切换到QHBoxLayout,则只需在类定义行中更改它,而不是在init方法中更改它.

所以你有它.不确定这是否真的特定于PySide,或更普遍地编写子类.

我不确定Lutz,他似乎非常犹豫是否支持使用super,会说(也许使用super违反了'Explicit比隐含'更好,对于初学者而言).当我试图更好地理解他对函数的关注时,我将在此上发布更多内容.


归档时间:

查看次数:

8710 次

最近记录:

6 年,10 月 前