问题 Python类:继承与实例化


我正在创建一个使用Frame()作为基类的GUI类。

在我的GUIclass的init方法中,我想创建一个Frame小部件

现在我有:

class GUIclass(Frame):
    def __init__(self, parent):
        frame = Frame(self, parent)   

但我在其他地方已经看到了第三行:

Frame.__init__(self, parent)   

我是编程,python和绝对继承的新手,我想知道我是否正确理解了两者之间的区别。我承诺,我做了很多研究和阅读,但我找不到任何能让它完全清楚的东西:

在第一种情况下,我没有调用init方法,因为我创建了一个Frame对象(frame),当创建一个对象时,它的init方法被python隐式调用。

在第二个场景中,一个是在类上调用init方法(我认为这是完全合法的?),因为没有创建Frame对象,因此不会自动执行。

是对的吗?

我也看到了:

frame = Frame.__init__(self, parent)   

这真的让我失望了。这只是某人做多余的事情还是有理由这样做?

感谢您的帮助,我想暂时放慢速度并确保我完全理解我编写的任何代码行,而不是编写和运行整个程序,我不明白。


5209
2018-05-15 22:43


起源

你应该使用第二个: Frame.__init__(self, parent) - Malik Brahimi
第一个是不正确的,因为它在基于帧的对象的初始化器中创建了不必要的帧。 - Malik Brahimi
第二个和第三个是对帧中父级初始值设定项的超级调用,这样子类的初始值设定项将扩展基础,而不是覆盖基础。但是没有必要分配超级呼叫的结果使第三个不正确。 - Malik Brahimi
最好的解决方案是使用 super().__init__(*arguments)(假设python3)在python2中这将是 super(GUIclass, self).__init__(*arguments) (假设新式课程)。此外,PEP8要求召集课程 GUIClass。 - Sebastian Riese
不幸的是,Tkinter不支持超级电话, - Burkely91


答案:


你应该打电话

super(GUIclass, self).__init__(parent)

这是调用(全部)继承的正确方法 __init__() 方法)。在许多情况下,与上述相比,它具有相同的结果

Frame.__init__(self, parent)

它只缺少关于继承关系的抽象,并说明了类 Frame 作为独一无二的班级 __init__() 您可能想要调用的方法(稍后会详细介绍)。

还提到了

frame = Frame(self.parent)

在这种情况下是错误的。它属于另一种对象关系模式,即 内容 关系而不是 遗产 关系(你的目标)。它会 创建 一个新的阶级对象 Frame 而不是初始化 Frame 你自己的一部分;在继承关系中你  一个 Frame,所以你必须初始化 yourself 作为一个以及初始化你的专业部分(这是在你的其余部分完成) __init__() 方法)。在 内容 关系模型你只是  一个 Frame

现在,我之间在调用之间提到的“轻微”差异呢 super(GUIclass, self).__init__(parent) 和 Frame.__init__(self, parent)

要了解您需要深入了解继承关系及其提供的各种可能性,尤其是多重继承。

考虑一个菱形关系模型,如下所示:

          Frame
          /   \
    GUIclass  SomeOtherClass
          \   /
       AnotherClass

在您当前的场景中,您只有左上角的两个类,但是一个人永远不知道会发生什么,并且您应该总是以某种方式编写代码,以便代码的下一个用户保留所有选项。

在这个菱形图案中你有 AnotherClass 继承 GUIClass 和 SomeOtherClass 而这又继承了 Frame

如果您现在使用该模式 Frame.__init__(self, parent) 同时 GUIclass 和 SomeOtherClass然后打电话给他们 __init__() 来自的方法 __init__() 的方法 AnotherClass 将导致双倍的呼叫 Frame__init__() 方法。这通常不是预期的,并且要注意不会发生这种情况, super 电话是发明的。一个体面的调用命令会调用每个调用它 __init__() 方法只有一次。


8
2018-05-15 23:03



该 super 参数以其他顺序排列。 - user2357112
谢谢,修好了。 (我从来没有记得那些正确的,所以如果你恶作剧我,我只是改变了那个;-) - Alfe
啊,现在一切都有意义,我想我看到了区别。那么我是否正确地说第一个在技术上初始化一个框架,但它创建一个单独的框架对象而不是说这个对象具有这些框架属性然后一些 - 然后一些是我的子类中的其他任何东西 在里面? - Burkely91
我也看到了制作代码的用处,当其他人出现时,这些代码不会崩溃,现在我只是单独做,但我希望有一天能成为一名程序员,所以这是我没想过的好建议然而。现在最好进入练习!如果可以的话,我会加十点 - Burkely91
是的,第一个 创建 一个单独的对象,并没有初始化框架方面 self。是否Tkinter支持 super:任何继承的类 object 支持 super 机制。我不确定哪个Tkinter类是你的Frame,但是你可以看看 Frame.__bases__ 看看是否 <type 'object'> 是由它继承的。如果不是,请不要使用 super 机制但坚持 Frame.__init__(self, parent) 模式。 - Alfe


你必须使用 Frame.__init__(self, parent) 因为Tkinter不支持超级电话


1
2018-06-14 04:56