简体   繁体   English

Python类:继承与实例化

[英]Python classes: Inheritance vs Instantiation

I'm creating a GUIclass that uses Frame() as its base class. 我正在创建一个使用Frame()作为基类的GUIclass。

In my GUIclass's init method I want to create a Frame widget 在我的GUIclass的init方法中,我想创建一个Frame小部件

Right now I have: 现在我有:

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

But I've seen this elsewhere for the third line: 但我在其他地方见过第三行:

Frame.__init__(self, parent)   

I'm new to programming, python and definitely inheritance and I wanted to know if I understand the difference between the two correctly. 我是编程,python和绝对继承的新手,我想知道我是否正确理解了两者之间的区别。 I did a lot of researching and reading, I promise, but I couldn't quite find anything that made it completely clear: 我保证,我做了大量的研究和阅读,但我找不到任何能让它完全清楚的东西:

In the first situation I don't call the init method as I created a Frame object (frame) and when an object is created its init method is called implicitly by python. 在第一种情况下,我没有调用init方法,因为我创建了一个Frame对象(frame),当创建一个对象时,它的init方法被python隐式调用。

In the second scenario, one is calling the init method on the class (which I believe is totally legit?) because a Frame object wasn't created, so therefore wouldn't do it automatically. 在第二个场景中,一个是在类上调用init方法(我认为这是完全合法的?),因为没有创建Frame对象,因此不会自动执行。

Is that right? 那正确吗?

I've also seen: 我也看到了:

frame = Frame.__init__(self, parent)   

which really threw me off. 这真的让我失望了。 Is this just someone doing something redundant or is there a reason for this? 这只是某人做了多余的事情还是有理由这样做?

Thank you for your help, I want to take it slow for now and make sure I fully understand any and every line of code I write as I go rather than writing and running a whole program I half understand. 感谢您的帮助,我想暂时放慢速度并确保我完全理解我编写的任何代码行,而不是编写和运行我理解的整个程序。

You should call 你应该打电话

super(GUIclass, self).__init__(parent)

This is the proper way to call (all) your inherited __init__() method(s). 这是调用(全部)继承的__init__()方法的正确方法。 It has in many cases identical results compared to the mentioned 与上述相比,它在许多情况下具有相同的结果

Frame.__init__(self, parent)

which only lacks the abstraction concerning the inheritance relationships and states the class Frame as the one and only class whose __init__() method you might want to call (more about that later). 它只缺少有关继承关系的抽象,并将类Frame为您可能想要调用的__init__()方法的唯一类(稍后会详细介绍)。

The also mentioned 还提到了

frame = Frame(self.parent)

is wrong in this context. 在这种情况下是错误的。 It belongs to another pattern of object relationship, namely contents relationship instead of inheritance relationship (which you aim at). 它属于另一种对象关系模式,即内容关系而不是继承关系(你的目标)。 It will create a new object of class Frame instead of initializing the Frame parts of yourself; 它将创建一个Frame类的新对象,而不是初始化自己的Frame部分; in inheritance relationships you are a Frame , so you have to initialize yourself as one as well as initializing your specialized parts (which is done in the rest of your __init__() method). 在继承关系中,你一个Frame ,所以你必须将yourself初始化为一个以及初始化你的专用部分(这在你的__init__()方法的其余部分完成)。 In contents relationship models you merely have a Frame . 内容关系的模型,你只是一个Frame

Now, what about that "slight" difference I mentioned above between calling super(GUIclass, self).__init__(parent) and Frame.__init__(self, parent) ? 现在,我在调用super(GUIclass, self).__init__(parent)Frame.__init__(self, parent)之间提到的“轻微”差异怎么样?

To understand that you need to dig deeper into inheritance relationships and the various possibilities these offer, especially with multiple inheritance. 要了解您需要深入了解继承关系及其提供的各种可能性,尤其是多重继承。

Consider a diamond-shaped relationship model which looks like this: 考虑一个菱形关系模型,如下所示:

          Frame
          /   \
    GUIclass  SomeOtherClass
          \   /
       AnotherClass

In your current scenario you only have the top left two classes, but one never knows what's going to come, and you should always code in a way so that the next user of your code keeps all options. 在您当前的场景中,您只有左上角的两个类,但是一个人永远不知道会发生什么,并且您应该总是以某种方式编写代码,以便代码的下一个用户保留所有选项。

In this diamond-shaped pattern you have AnotherClass which inherits GUIClass and SomeOtherClass which in turn both inherit Frame . 在这个菱形图案中,你有AnotherClass继承GUIClassSomeOtherClass GUIClass ,它们都继承了Frame

If you now use the pattern Frame.__init__(self, parent) in both GUIclass and SomeOtherClass , then calling their __init__() methods from the __init__() method of AnotherClass will result in a doubled calling of the Frame 's __init__() method. 如果你现在使用的模式Frame.__init__(self, parent)在这两个GUIclassSomeOtherClass ,然后把他们的__init__()从方法__init__()的方法AnotherClass将导致的一倍调用Frame__init__()方法。 This typically is not intended, and to take care that this does not happen, the super call was invented. 这通常不是预期的,并且为了不会发生这种情况,发明了super呼叫。 It takes care that a decent calling order calls each of the __init__() methods only and exactly once. 注意一个体面的调用命令只调用每个__init__()方法并且只调用一次。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM