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

Поделиться
HTML-код
  • Опубликовано: 26 янв 2025

Комментарии • 69

  • @FromJWtoJesus
    @FromJWtoJesus 4 дня назад

    Не перестаю удивляться способности Преподавателя делать сложное простым. Этот курс поистине подарок для тех тысяч подписчиков, которые его просмотрели.

  • @rioriocccp5929
    @rioriocccp5929 Год назад +20

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

  • @Лена-в1н6ы
    @Лена-в1н6ы Год назад +8

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

  • @nomadicus77
    @nomadicus77 Год назад +6

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

  • @ТимонЯблоков
    @ТимонЯблоков 2 года назад +24

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

  • @siarheiulas6969
    @siarheiulas6969 Год назад +3

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

  • @vb52ru
    @vb52ru 2 года назад +4

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

    • @selfedu_rus
      @selfedu_rus  2 года назад +4

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

  • @n0rmaLman
    @n0rmaLman 2 года назад +7

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

  • @mrfang5908
    @mrfang5908 2 года назад +4

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

    • @Watcherfromfar
      @Watcherfromfar 10 месяцев назад +1

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

  • @freeforrussia
    @freeforrussia 2 года назад +3

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

  • @taran_dm
    @taran_dm 2 месяца назад

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

  • @andredru4278
    @andredru4278 11 месяцев назад +1

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

  • @ПавлоКабай
    @ПавлоКабай 2 года назад +3

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

  • @h4ckkk
    @h4ckkk 2 года назад +3

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

  • @dmitrykhomyakov8451
    @dmitrykhomyakov8451 2 года назад +4

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

    • @selfedu_rus
      @selfedu_rus  2 года назад

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

  • @ЕрвандАгаджанян-в3к
    @ЕрвандАгаджанян-в3к 2 года назад +2

    Спасибо!

  • @CultureofSpeech
    @CultureofSpeech 9 месяцев назад +1

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

  • @gayratsaidakhmedov5451
    @gayratsaidakhmedov5451 11 месяцев назад +1

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

    • @selfedu_rus
      @selfedu_rus  11 месяцев назад

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

  • @unaibekovbakhyt6517
    @unaibekovbakhyt6517 2 года назад +3

    Спасибо

  • @ne_zabyc_dadac
    @ne_zabyc_dadac 2 года назад +3

    Неожиданно

  • @johnmazepa
    @johnmazepa Год назад +1

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

    • @hunterxvov4ik
      @hunterxvov4ik 11 месяцев назад +1

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

  • @yuraliashenko6054
    @yuraliashenko6054 2 года назад +2

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

    • @selfedu_rus
      @selfedu_rus  2 года назад

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

  • @daniyarutegilishev3591
    @daniyarutegilishev3591 2 года назад +2

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

    • @selfedu_rus
      @selfedu_rus  2 года назад +2

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

  • @jur3063
    @jur3063 2 года назад +1

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

  • @chayok9923
    @chayok9923 2 года назад +2

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

    • @selfedu_rus
      @selfedu_rus  2 года назад +5

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

    • @chayok9923
      @chayok9923 2 года назад +1

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

  • @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 😝 . Уже разобрался, спасибо 😉

  • @Alukard-789
    @Alukard-789 Год назад +2

    👍👍👍👍👍

  • @ЛешаМакентоша
    @ЛешаМакентоша 2 года назад +2

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

    • @selfedu_rus
      @selfedu_rus  2 года назад

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

  • @zakirovio
    @zakirovio Год назад +1

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

    • @selfedu_rus
      @selfedu_rus  Год назад +1

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

    • @zakirovio
      @zakirovio Год назад

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

  • @СарматПересветов
    @СарматПересветов Год назад +2

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

    • @selfedu_rus
      @selfedu_rus  Год назад +1

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

    • @СарматПересветов
      @СарматПересветов Год назад +1

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

    • @selfedu_rus
      @selfedu_rus  Год назад

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

    • @VitalyTolmachev
      @VitalyTolmachev Год назад +1

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

  • @MrSasuke1337
    @MrSasuke1337 Год назад

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

  • @Cygni7
    @Cygni7 Год назад +1

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

    • @selfedu_rus
      @selfedu_rus  Год назад

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

    • @Cygni7
      @Cygni7 Год назад

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

    • @rukigaki
      @rukigaki Год назад

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

  • @gta_KaskaD
    @gta_KaskaD 2 года назад +1

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

    • @borisharitonovgachi3506
      @borisharitonovgachi3506 2 года назад

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

  • @ibrahimoglu
    @ibrahimoglu 2 года назад +3

    👍

  • @youtubeyoutube6205
    @youtubeyoutube6205 2 года назад +4

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

    • @selfedu_rus
      @selfedu_rus  2 года назад +3

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

  • @konil658
    @konil658 4 месяца назад +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)

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

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

    • @selfedu_rus
      @selfedu_rus  Год назад

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

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

      @@selfedu_rus спасибо

  • @gayratsaidakhmedov5451
    @gayratsaidakhmedov5451 11 месяцев назад +1

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

  • @fahrenheit1863
    @fahrenheit1863 2 года назад +1

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

  • @jaksonmillka
    @jaksonmillka 4 месяца назад

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

  • @mikhailihnatouski1215
    @mikhailihnatouski1215 6 месяцев назад

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

  • @ДмитрийДегтярев-в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_*_ -> ..._
      Дальше даже нет смысла рассматривать, так как уже видно, что в цепочке один из классов повторился несколько раз, что в свою очередь неизбежно ведет к ситуации, когда родитель окажется впереди своего потомка, а такового в этом алгоритме быть не должно!