Классы Python: Наследование и инстанцирование

Я создаю GUIclass, который использует Frame() в качестве базового класса.

В моем методе init GUIclass я хочу создать виджет 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)   

который действительно меня отбросил. Это просто кто-то делает что-то лишнее или есть причина для этого?

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

Ответ 1

Вы должны позвонить

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__() только один раз.

Ответ 2

Вам нужно будет использовать Frame.__init__(self, parent), поскольку Tkinter не поддерживает супервызов