#25. Множественное наследование | Объектно-ориентированное программирование Python

Поділитися
Вставка
  • Опубліковано 25 лис 2024
  • Курс по Python ООП: stepik.org/a/1...
    Как работает множественное наследование (multiple inheritance) в Python. Зачем это нужно. Пример использования при реализации идеи минсинов (mixins). Алгоритм обхода базовых классов MRO.
    Плейлист по Python ООП: • Объектно-ориентированн...
    Инфо-сайт: proproprogs.ru...
    Telegram-канал: t.me/python_se...

КОМЕНТАРІ • 68

  • @rioriocccp5929
    @rioriocccp5929 Рік тому +18

    как лёгкий пример множественного наследования - молоко(жидкость, еда)
    жидкость (вязкость, температура кипения), еда (белки углеводы жиры, калории)
    или куртка (одежда, товар)
    одежда (размер), товар (цена)
    по сути это пересекающиеся круги эйлера
    п. с. комент в поддержку видео

  • @Лена-в1н6ы
    @Лена-в1н6ы 11 місяців тому +6

    Сначала у меня были вопросы, а потом я просто еще раз посмотрела видео... И оказывается все понятно! Вот что значит: "внимательно слушай учителя и будет тебе счастье".

  • @ТимонЯблоков
    @ТимонЯблоков 2 роки тому +24

    Ещё один пример - класс Datetime, который наследуется от Date и Time. Иногда нужно работать отдельно с датой, иногда со временем, а иногда и с тем, и с другим.

  • @nomadicus77
    @nomadicus77 Рік тому +6

    очень интересно и познавательно для меня это наверное самый лучший и интересный урок, так как скоро проект в Джанго буду делать, а там много миксинчиков играет роль, благодарю наставник

  • @siarheiulas6969
    @siarheiulas6969 Рік тому +3

    Сергей, спасибо за урок! Очень нравится Ваш курс!

  • @taran_dm
    @taran_dm 17 днів тому

    Спасибо за труд!

  • @n0rmaLman
    @n0rmaLman 2 роки тому +7

    Читал про миксины в 'Книге рецептов' Бизли, Джонс. Довольно специфическая штука. Наверное стоит её отдельно от множественного наследия рассматривать.

  • @andredru4278
    @andredru4278 8 місяців тому +1

    Спасибо. Принцип понятен.

  • @freeforrussia
    @freeforrussia 2 роки тому +3

    Спасибо огромное, Сергей!
    👍👍👍

  • @vb52ru
    @vb52ru 2 роки тому +4

    Ух ты продолжение)

    • @selfedu_rus
      @selfedu_rus  2 роки тому +4

      перезалив, небольшая ошибка была ))

  • @ПавлоКабай
    @ПавлоКабай Рік тому +3

    классный курс

  • @mrfang5908
    @mrfang5908 2 роки тому +4

    такая полезная инфа, а так мало просмотров, очень жаль

    • @Watcherfromfar
      @Watcherfromfar 8 місяців тому +1

      Совсем не мало. Это 24 тысячи учебных просмотров. Даже если это всего 5-10к будущих разработчиков, это уже огромная цифра, которая показывает ценность работы автора. Шутка ли, учитель в школе столько учеников лет за 10 обучает, а тут за год столько. По мне - это очень круто. Тем более тема не первая, это 25-й урок!

  • @h4ckkk
    @h4ckkk 2 роки тому +3

    Отлично.Спасибо.

  • @unaibekovbakhyt6517
    @unaibekovbakhyt6517 2 роки тому +3

    Спасибо

  • @ЕрвандАгаджанян-в3к

    Спасибо!

  • @dmitrykhomyakov8451
    @dmitrykhomyakov8451 Рік тому +4

    Сергей спасибо огромное за видео! Материал подаете очень доступно и понятно. Не многие могут подать столь сложный материал в доступной форме. Но вопросы все таки есть: когда вы рассказываете о порядке перебора метода init 6:32 используете слайд на котором рисуете стрелки, но Ваши стрелки не совпадают со стрелками слайда. Ваше рассуждения не вызывают вопросов, но тогда получается ошибка в стрелках на слайде?

    • @selfedu_rus
      @selfedu_rus  Рік тому

      Спасибо! Да, на слайде - это стрелки структуры множественного наследования классов, а не порядок вызова init(), отсюда и расхождения.

  • @CultureofSpeech
    @CultureofSpeech 7 місяців тому +1

    А когда будет продолжение этой темы разговора подробнее ⁉️

  • @ne_zabyc_dadac
    @ne_zabyc_dadac 2 роки тому +3

    Неожиданно

  • @ibrahimoglu
    @ibrahimoglu 2 роки тому +3

    👍

  • @gayratsaidakhmedov5451
    @gayratsaidakhmedov5451 9 місяців тому +1

    3:14 Сергей (простите меня) - так делать тоже не желательно . Вы весь курс повторяли, что это плохой тон и подобное следует реализовывать через определение класса (либо вводить метод класса для обработки ID).

    • @selfedu_rus
      @selfedu_rus  9 місяців тому

      Все на уровне рекомендаций и чтобы не сильно усложнять текст программы, иногда можно отходить от этих рекомендаций.

  • @Anonim-im6ln
    @Anonim-im6ln Рік тому +2

    👍👍👍👍👍

  • @chayok9923
    @chayok9923 2 роки тому +2

    Вы это видео выложили в общий доступ. Он же платный, по ссылке только должен работать)

    • @selfedu_rus
      @selfedu_rus  2 роки тому +5

      В курсах самое ценное - это задания и их проверка, т.е. практика. Все остальное должно быть бесплатным.

    • @chayok9923
      @chayok9923 2 роки тому +1

      @@selfedu_rus понял, у Вас весь курс просто ниже, а это перезалив ролика. Спасибо!

  • @daniyarutegilishev3591
    @daniyarutegilishev3591 2 роки тому +2

    Сергей доброго дня, какие мысли у вас о том что о наследовании говорят как о плохом примере использования при построении архитектуры, можете рассказать о паттернах в вашем видении!

    • @selfedu_rus
      @selfedu_rus  2 роки тому +2

      Без наследования нет полноценного ООП - это могу определенно сказать. Другое дело, все в меру. Не нужно "лепить" слишком много базовых классов. Как всегда должна быть золотая середина.
      С паттернами немного знакомлю на курсе по Python ООП. Возможно, в будущем расширю этот раздел.

  • @yuraliashenko6054
    @yuraliashenko6054 2 роки тому +2

    Спасибо за урок, подскажите как через super() вызвать метод print_info() именно из Mixinlog?

    • @selfedu_rus
      @selfedu_rus  2 роки тому

      для надежности придется написать Mixinlog.print_info() но классы нужно проектировать так, чтобы этого не требовалось

  • @Munchen888
    @Munchen888 Рік тому +1

    Сергей, здравствуйте. Такой вопрос: как так выходит, что порядок MRO выводит: Notebook, Goods, MixinLog, MixinLog2, если у вас в примере видел, что инициализатор Goods выводит сообщение последним? Какое-то несоответствие тому, что выводит инициализатор и порядок MRO.

    • @rukigaki
      @rukigaki Рік тому +1

      Порядок mro будет таким каким вы его написали. Что касается порядка выводов print, то вы сперва делегируете вызов функции на следующий класс в этой иерархии, а только потом уже инициализируете свои атрибуты и вызываете print в класса Goods, тоесть вы спервы вызываете super().__init__, там отрабатывает свой print, который находистя в инцииализаторе класса MaxinLog, и только потом выводится print класса Goods.

    • @Munchen888
      @Munchen888 Рік тому

      @@rukigaki 😝 . Уже разобрался, спасибо 😉

  • @jur3063
    @jur3063 2 роки тому +1

    очень странно, у меня почему-то save_cell_log сразу сработал. может это как-то от версии зависит?

  • @zakirovio
    @zakirovio Рік тому +1

    получается можно сказать, что миксины при необходимости, расширяют функционал базового класса? допустим, на основе базы создано множество дочерних, а к только к некоторым из низ нужно добавить доп методы, тогда к этим класса добавляют наследование от определенного миксина

    • @selfedu_rus
      @selfedu_rus  Рік тому +1

      Микмины, скорее, как кирпичики, из которых можно конфигурировать функциональность дочерних классов.

    • @zakirovio
      @zakirovio Рік тому

      @@selfedu_rus благодарю)

  • @Cygni7
    @Cygni7 Рік тому +1

    Здравствуйте, возник один вопрос : не получится ли для последней цели из видео написать что-то вроде super().super().print_info()? Просто интересно. Спасибо за видео!

    • @selfedu_rus
      @selfedu_rus  Рік тому

      Думаю, не лучшая конструкция, т.к. super() просматривает базовые классы по списку MRO, и это может легко привести к ошибке.

    • @Cygni7
      @Cygni7 Рік тому

      Ещё такой вопрос, как вы делаете несколько строк комментарием за одно нажатие? Если выделить все и нажать решётку то оно просто заменяется у меня. Заранее спасибо

    • @rukigaki
      @rukigaki Рік тому

      @@Cygni7 Сочетание клавиш ctrl + /

  • @ЛешаМакентоша
    @ЛешаМакентоша 2 роки тому +2

    А верно, что метод super() всегда возвращает вспомогательный класс для работы методов класса, идущего вторым в коллекции __mro__?

    • @selfedu_rus
      @selfedu_rus  2 роки тому

      super - это класс, поэтому super() - формирование специального объекта-посредника, через который и происходит обращение к базовому классу в соответствии с порядком коллекции __mro__

  • @johnmazepa
    @johnmazepa Рік тому +1

    5:39 - и все-таки Синьору пришлось лезть руками в базовый класс и вписывать в строку №3 код "инициализатора родительского класса"
    Это допустимая погрешность в случаях, когда "Синьора просят добавить функционал без вмешательства в базовый класс"?

    • @hunterxvov4ik
      @hunterxvov4ik 9 місяців тому +1

      это нарушение OCP

  • @konil658
    @konil658 2 місяці тому +1

    А чем такая плоха реализация
    class CLS_A:
    def __init__(self, atr_a):
    self.str_a = 'STR_AAA :' + atr_a
    class CLS_B:
    def __init__(self, atr_b):
    self.str_b = 'STR_BBB: ' + atr_b
    class CLS_C(CLS_A, CLS_B):
    def __init__(self, atr_a, atr_b):
    super().__init__(atr_a)
    CLS_B.__init__(self, atr_b)
    exmpl = CLS_C('клас a', 'класс b')
    print(exmpl.str_a, exmpl.str_b)

  • @youtubeyoutube6205
    @youtubeyoutube6205 2 роки тому +4

    а что если в конструкторе основного базового класса принимать ещё и kwargs, а потом их передавать в конструкторы всех следующих классов, тогда по идее каждый будет брать свои аргументы и порядок не будет иметь значение

    • @selfedu_rus
      @selfedu_rus  2 роки тому +3

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

  • @MrSasuke1337
    @MrSasuke1337 Рік тому

    Музыка будто из гравити фолз в конце)

  • @СарматПересветов

    почему нельзя в __init__ конечного класса наследника, просто не вызвать через имена классов родителей методы __init__ в нужном порядке и нужными параметрами?

    • @selfedu_rus
      @selfedu_rus  Рік тому +1

      путаница получится, т.к. скоро забудете, кто из кого вызывается и редактировать это будет очень сложно

    • @СарматПересветов
      @СарматПересветов Рік тому +1

      @@selfedu_rus вопрос очень спорный, т. к. у нас может быть много классов предков, каждый со своими параметрами (рассматриваю наихудший вариант). в результате можно быстрее запутаться перетаскивая параметры через функцию super().__init__(). Но, все равно спасибо!

    • @selfedu_rus
      @selfedu_rus  Рік тому

      @@СарматПересветов это уже к вопросу проектирования программного кода. Желательно такого избегать (по возможности).

    • @VitalyTolmachev
      @VitalyTolmachev Рік тому +1

      @@selfedu_rus Посмотрел все ваши предыдущие видео по ООП и там все четко и понятно, а при просмотре этого видео все мое понимание ООП выставило штыки и отказалось принимать информацию. Тут нарушены все принципы ООП. один родительский класс ссылается на другой . Плюс для для создания дочернего класса мы изменяем родительский. А если он из какой-нить библиотеки? Я тоже считаю что вызовы __init__ возможны только из дочернего класса без изменений родительского. Специально пошел искать эту инфу у других авторов. Егоров, в своем курсе, вызывает все из дочернего . Не смотря на это видео, остальной курс, из того что я успел посмотреть, супер. Спасибо! Продолжаю изучать ООП

  • @АртемНиконов-у7я

    Сергей, а зачем у класса Miksinlog2 есть функция super , если этот класс находится в конце по наследованию и в свою очередь не вызывает никаких инициализаторов?

    • @selfedu_rus
      @selfedu_rus  Рік тому

      Это для общности, если появится класс Miksin3 или порядок в наследовании поменяется.

    • @АртемНиконов-у7я
      @АртемНиконов-у7я Рік тому

      @@selfedu_rus спасибо

  • @gta_KaskaD
    @gta_KaskaD 2 роки тому +1

    11:02 не лутше писать super().__init__(*args,**kwargs) ?

    • @borisharitonovgachi3506
      @borisharitonovgachi3506 2 роки тому

      А ты откуда вы их возьмете? Эти параметры используются при инициализации метода, вы не сможете послать их в аргументе уже готового метода. Чтобы использовать их в качестве аргумента, вам надо явно где-то в классе этот кортеж(список, множество) args и словарь kwargs определить, только зачем? Более того, первым элементом кортежа должна быть ссылка на объект)

  • @gayratsaidakhmedov5451
    @gayratsaidakhmedov5451 9 місяців тому +1

    Видимо действительно сложно применимый функционал
    2:26 - интернет магазин по продаже товаров - десятки тысяч дочерних классов товаров - и тут наш "хороший senior" решил применить идею миксинов😅
    поменьше бы таких "хороший senior" разработчиков))

  • @fahrenheit1863
    @fahrenheit1863 2 роки тому +1

    Чем то похоже на декораторы.

  • @jaksonmillka
    @jaksonmillka 2 місяці тому

    Урок #25 = Пройден

  • @mikhailihnatouski1215
    @mikhailihnatouski1215 4 місяці тому

    Все-же Пито - это уродский язык. Автор, поначалу, хотел быть оригинальным, затем четверть века исправляет собственную дурь.

  • @ДмитрийДегтярев-в3ю

    Приветствую вас, можете пожалуйста указать на ошибку в моем коде
    import datetime
    class Merchendise:
    def __init__(self, name_thing, wight, price):
    super().__init__()
    self.name_thing = name_thing
    self.wight = wight
    self.price = price
    def mech_method(self):
    return f'{self.name_thing}, {self.wight}, {self.price}'
    class Thing(Merchendise):
    thing = 0
    def thing_method(self):
    super().__init__(self.name_thing, self.wight, self.price)
    self.thing += 1
    price = self.thing * self.price
    return price
    class Time(Thing):
    date_time = datetime.datetime(year=2023, month=12, day=12)
    def __init__(self, date_time):
    super().__init__(self.name_thing, self.wight, self.price)
    self.date_time = date_time
    def time_method(self):
    self.thing_method()
    time = self.date_time + datetime.timedelta(days=self.thing)
    return time
    class ElectroGuitar(Merchendise, Thing, Time):
    pass
    eg = ElectroGuitar('Ibanez', 1.5, 220000)
    print(eg.time_method())
    print(eg.thing_method())
    print(eg.mech_method())
    #ошибка
    class ElectroGuitar(Merchendise, Thing, Time):
    TypeError: Cannot create a consistent method resolution
    order (MRO) for bases Merchendise, Thing, Time

    • @rukigaki
      @rukigaki Рік тому

      Потому что алгоритм MRO должен соблюдать детерминированный порядок поиска атрибутов в иерархии наследования. Но в вашем случае он сталкивается с явным противоречием.
      Смотрите сами:
      _ElectroGuitar -> Merchendise -> _*_Thing_*_ -> Time -> _*_Thing_*_ -> ..._
      Дальше даже нет смысла рассматривать, так как уже видно, что в цепочке один из классов повторился несколько раз, что в свою очередь неизбежно ведет к ситуации, когда родитель окажется впереди своего потомка, а такового в этом алгоритме быть не должно!