#45. Введение в декораторы функций | Python для начинающих

Обучающий курс: stepik.org/course/100707
Что такое декораторы, как они определяются и применяются к функциям. Примеры их использования.
Telegram-канал: t.me/python_selfedu
#37. Алгоритм Евклида для нахождения НОД: • #37. Алгоритм Евклида ...
#43. Области видимости переменных: • #43. Области видимости...
#44. Замыкания в Python: • #44. Замыкания в Pytho...

Пікірлер: 104

  • @nikitaaspaev1638
    @nikitaaspaev16387 ай бұрын

    Посмотрел сначала видео Гоши Дударя. Ничерта не понял. Потом посмотрел ваше видео - разница в преподавании колоссальна! Вы просто безупречно, на простых примерах, объясняете тему, спасибо вам!

  • @user-vt3cq8eu8s
    @user-vt3cq8eu8sАй бұрын

    Коммент в поддержку канала!)

  • @onemasterlomaster1829
    @onemasterlomaster18292 жыл бұрын

    selfedu *Благодаря замыканию, у меня аж мозг замкнуло! Как это все запутано, 7 раз пересмотрел! Спасибо Сергей без вас не разобрался бы!*

  • @tinaanit2965
    @tinaanit2965Ай бұрын

    пришла по рекомендации из какого-то комментария ) и не пожалела , спасибо за ваше объяснений ! Развития вашему каналу🍀

  • @user-lq4pv8lj5q
    @user-lq4pv8lj5q Жыл бұрын

    с четвёртого раза нашёл ролик, который понятно простым языком объясняет, что такое декораторы, спасибо!

  • @user-wr5rc5pp8r
    @user-wr5rc5pp8r2 жыл бұрын

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

  • @SovsemNeProstoy
    @SovsemNeProstoy Жыл бұрын

    Как-же вы всё прекрасно разжевали нам, за несколько жалких минут понял то, что не понимал в течении месяца. *чувства искренней благодарности*

  • @nedestro
    @nedestro2 жыл бұрын

    Сперва смотрел прошлый вариант видео (от 16 мар. 2020) и там к середине мозги начали заворачиваться, я несколько раз на паузу ставил, отматывал, потом просто досмотрел с чувством "пока рановато, позже обязательно раскурю". А здесь всё с ходу понятно! Декоратор был написан буквально "с полпинка", сижу довольный как слон )) Новая подача зашла шикарно, спасибо огромное!

  • @kiber7575
    @kiber75752 ай бұрын

    мега круть про декораторы

  • @user-bp7nu3eu8d
    @user-bp7nu3eu8d Жыл бұрын

    Все очень понятно изложено, спасибо! Теперь не понимаю, как я могла этого не понимать))

  • @qryak
    @qryak9 ай бұрын

    пожалуй это самая сложная тема после рекурсии, с вашими уроками хоть как-то начал ее понимать)

  • @user-tb2jp7kg2c
    @user-tb2jp7kg2c2 жыл бұрын

    Сергей, спасибо! Курс крутой, возможно когда-нибудь дойдем до асинхронности в Python, был бы рад послушать и изучить в вашей интерпретации информацию про asyncio и т.д.

  • @AZ993k

    @AZ993k

    Жыл бұрын

    Да так не то до асинхронности можно дойти, но и до паттернов проектирования на питоне :) Ме, например, очень нравился всегда C#, учить я его пытался в основном самостоятельно (были курсы, но неудачные). Но по сравнению с C# питон заходит намного быстрее. Думаю, дело в преподавателе

  • @user_712_li
    @user_712_li Жыл бұрын

    Спасибо огромное, автор. Единственный, кто подробно всё объяснил.

  • @user-iq6uq4lx3l

    @user-iq6uq4lx3l

    Жыл бұрын

    @PythonRussian - объясняет просто "жесть", вообще МОЛОДЕЦ парнишка!Посмотри не прогадаешь - объясняет может даже лучьше

  • @DobroDelo
    @DobroDelo Жыл бұрын

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

  • @likeclockwork9600
    @likeclockwork96002 жыл бұрын

    Я тут цикл для себя написал, рекомендую ознакомиться. while ' Сергей выкладывает видео ': like += 1 comment += 1 print('Спасибо Сергей') else: print('Ждем новое видео')

  • @krab9241

    @krab9241

    2 жыл бұрын

    пока иначе. а так можно было!?

  • @likeclockwork9600

    @likeclockwork9600

    2 жыл бұрын

    @@krab9241 да , такое условие есть только у Пайтона. (после цикла можно поставить else) Но сам Гвидо говорил, если бы он заново начал делать Python, то не стал бы делать такое условие.

  • @KonstantinYurievich

    @KonstantinYurievich

    2 жыл бұрын

    @@likeclockwork9600 'else' в 'while' используется в комбинации с 'break', иначе в 'else' нет смысла...

  • @novichok3417

    @novichok3417

    3 ай бұрын

    Поздравляю вас с говнокодом! Создал бесконечный цикл. И зачем то увеличивал переменные like и comment

  • @user-ck2tv6pf6f

    @user-ck2tv6pf6f

    2 ай бұрын

    @@novichok3417 +

  • @MrSasuke1337
    @MrSasuke13375 ай бұрын

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

  • @user-uk3qb9ex1b
    @user-uk3qb9ex1b2 ай бұрын

    спасибо большое было очень полезно 🥰🥰🥰

  • @ruziliakalyon4168
    @ruziliakalyon41682 жыл бұрын

    Благодарю вас за обучение! Вы очень внимательный и ответственный учитель. Здоровья Вам и Вашим близким

  • @user-sm6ej3fl4m
    @user-sm6ej3fl4m8 ай бұрын

    Спасибо, это единственное видео где я все понял. Смотрел других, пересматривал по 3 раза но не понял. Большое спасибо автору!

  • @andredru4278
    @andredru42783 ай бұрын

    Спасибо. Великолепно. Я понял.

  • @user-hw9eg2om3g
    @user-hw9eg2om3g6 ай бұрын

    Хоть и понял со 2 раза, но материал понятен Огромное спасибо автору!

  • @86Blind
    @86Blind2 жыл бұрын

    Огромное спасибо за урок!

  • @user-lf1ez2ln7h
    @user-lf1ez2ln7h Жыл бұрын

    Лучшие объяснения из тех что я видел, хотя я давно пишу на питоне, но именно изучить его захотелось сейчас

  • @vladimirkulakov6126
    @vladimirkulakov61262 жыл бұрын

    Ура! Декораторы! А ведь именно на этой теме я засыпался на первом собеседовании) маст хев! Спасибо за короткое и понятное видео, Сергей!

  • @user-tg3xw1cb2l

    @user-tg3xw1cb2l

    2 жыл бұрын

    Сэр, Вы серьёзно? Не зная декораторов уже можно идти на собеседование?? Я думал это самое начало обучения...

  • @vladimirkulakov6126

    @vladimirkulakov6126

    2 жыл бұрын

    @@user-tg3xw1cb2l собеседование это в том числе опыт, не попробуешь не узнаешь.

  • @Grigorev84
    @Grigorev842 жыл бұрын

    Очень крутая подача, лучше ещё не видел!

  • @user-sb8zp4qn2y
    @user-sb8zp4qn2y8 ай бұрын

    Спасибо большое вам, очень ценные уроки😊

  • @user-vo4pj6cm9h
    @user-vo4pj6cm9h9 ай бұрын

    Отличное описание, автору спасибо!

  • @mksmvnv
    @mksmvnv8 ай бұрын

    просто идеальное объяснение, спасибо вам большое)

  • @konstantinsakharov227
    @konstantinsakharov227 Жыл бұрын

    Спасибо, у Вас дар! Видел много курсов, так ясно, наглядно и без лишнего усложнения не объясняет никто на русском. Всего Вам наилучшего, 100500+ в карму =) Это касается всех курсов которые здесь размещены.

  • @Ybuotue
    @Ybuotue2 жыл бұрын

    Едрён батон! Не один год работал с декораторами (которые художники), и только под конец видео поняв, что такое декораторы в питоне, на меня снизашло озарение, почему они названы так. Думаю если бы раньше связал два этих одинаковых слова, быстрее бы понял суть декорирования в питоне (считай ретушевание/корректировка/украшение фукнции). Вообще сильно помогла ссылка на Замыкания. Без замыканий реально было трудно понять суть и смысл. Спасибо.

  • @drueserick4158
    @drueserick4158 Жыл бұрын

    Я понял это намек, я все ловлю на лету... Но чета я совсем... ... Бллагодаря Вам, все лучше :)

  • @user-ye1vt4mj1p
    @user-ye1vt4mj1p Жыл бұрын

    Доброго времени суток, Сергей, заметил, что при задании функции get_fast_nod следующего вида: def get_fast_nod(a, b): while b: a, b = b, a % b return a она работает аналогично тому определению, которые Вы предоставили в видео. (т.к. по факту, если a < b, то в строчке a, b = b, a % b они просто поменяются местами)

  • @user-yw6nt4zz4c
    @user-yw6nt4zz4c Жыл бұрын

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

  • @user-rc7kz2qp9m
    @user-rc7kz2qp9m Жыл бұрын

    Супер, не знаю кто еще лучше может настолько понятно объяснить. Спасибо тебе большое)

  • @user-iq6uq4lx3l

    @user-iq6uq4lx3l

    Жыл бұрын

    @PythonRussian - объясняет просто "жесть", вообще МОЛОДЕЦ парнишка!

  • @wotlivehannel4612
    @wotlivehannel46122 ай бұрын

    Доброго времени суток. Спасибо за видео. Вопрос: могу ли я "продекорировать" функцию функцией-декоратором, в которой не замыкания?

  • @jetbrain9115
    @jetbrain91152 жыл бұрын

    Спасибо! Суппер!

  • @jamjam3337
    @jamjam3337 Жыл бұрын

    спасибо!👏👍

  • @Munchen888
    @Munchen8887 ай бұрын

    def gcd(a, b): if a == 0 or b == 0: return a + b elif a > b: return gcd(a % b, b) elif b > a: return gcd(a, b % a) print(gcd(30, 18)) Нахождение НОД рекурсивно) Чтобы не забывать!

  • @PavelNebo
    @PavelNebo Жыл бұрын

    Я посмотрел с десяток разных объяснений декораторов, но только сейчас я по-настоящему понял эту тему. Далеко не у каждого человека есть талант преподавателя, именно этот талант позволяет правильно ПРЕПОДАТЬ материал, чтобы он был понятен. Спасибо Вам, Сергей !

  • @mrpjetrov378

    @mrpjetrov378

    Жыл бұрын

    Что же у других тогда....

  • @a.osethkin55
    @a.osethkin55 Жыл бұрын

    Спасибо!

  • @andruhaz
    @andruhaz2 жыл бұрын

    Видимо всех замыкает на замыканиях)), но объяснение лучше чем у Била Любановича. Например меня заклинило на "КАААК можно передавать функции второе значение, когда ей уже раньше передали значение)) ПОЧЕМУ она его принимает". Видимо нужно еще раз перечитать вложенные функции)). Да и в принципе selfedu классно сделал, что показал, почему замыкание называется замыканием. Сразу практически все стало понятно. Еще стало понятно, что хочу поучить Фласк у selfedu

  • @gayratsaidakhmedov5451
    @gayratsaidakhmedov54515 ай бұрын

    спасибо

  • @user-yo2oi7qz3l
    @user-yo2oi7qz3l Жыл бұрын

    Спасибо,Сергей! Видео понятное,но всё же пример с алгоритмом Евклида может запутать!

  • @mrrototo761
    @mrrototo761 Жыл бұрын

    Спасибо

  • @user-rc9cz5ex6l
    @user-rc9cz5ex6l Жыл бұрын

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

  • @selfedu_rus

    @selfedu_rus

    Жыл бұрын

    Да, все верно. Набор параметров декорируемой функции, как правило, остается неизменным, но если хотите что то поменять, то прописывайте у def wrapper() это у будет набор параметров после декорирования.

  • @user-bw4xg8tb9r
    @user-bw4xg8tb9r2 жыл бұрын

    Урок супер! Всё предельно понятно и примеры хорошие. Спасибо! P.S. Интересно почему при первом вызове декарируемой функции get_nod время вывелось 0,0329.. сек, а не 0,0269 сек, как в последствии и перед этим))

  • @selfedu_rus

    @selfedu_rus

    2 жыл бұрын

    ОС Windows (скорее всего она у вас) - это не система реального времени и программы могут выполняться с разной скоростью

  • @justnothingnet
    @justnothingnet7 ай бұрын

    Legend

  • @alexzir
    @alexzir Жыл бұрын

    Подскажите пожалуйста, на Stepik у вас листинги кода прилагаются? И что там дополнительно есть?

  • @selfedu_rus

    @selfedu_rus

    Жыл бұрын

    дополнительно только практика

  • @user-cp6ne8nr4u
    @user-cp6ne8nr4u Жыл бұрын

    Спасибо большое, все вполне понятно. Я только не поняла, зачем в принципе нужны декораторы. Ну нельзя ли что-то делать, потом вызывать функцию, потом снова что-то делать?

  • @selfedu_rus

    @selfedu_rus

    Жыл бұрын

    во фреймворках они везде и всюду )) очень удобная штука, с практикой усвоите этот момент

  • @Pawokify
    @Pawokify Жыл бұрын

    Я не понял почему нужно в wrapper тоже прописывать параметр title.. (Если не использовать args)

  • @ibrahimoglu
    @ibrahimoglu2 жыл бұрын

    👍

  • @impellergimpeller5133
    @impellergimpeller51332 жыл бұрын

    👍👍👍👍👍

  • @guiterenzog2723
    @guiterenzog2723 Жыл бұрын

    Что по поводу __name__ и __doc__ при использовании нескольких декораторов?

  • @selfedu_rus

    @selfedu_rus

    Жыл бұрын

    да все то же самое, так где декорирование функции происходит, сохраняем __name__ и __doc__

  • @pokryshkin1973
    @pokryshkin1973 Жыл бұрын

    Если в классе есть setter для __old, то не разумно ли в методе __init__ прописать self.old = old вместо self.__old = old

  • @selfedu_rus

    @selfedu_rus

    Жыл бұрын

    да, разумно!

  • @pokryshkin1973

    @pokryshkin1973

    Жыл бұрын

    @@selfedu_rus перепутал тему. хотел спросить в kzread.info/dash/bejne/f6yqy6-wkqrSY6w.html&feature=share&EKLEiJECCKjOmKnC5IiRIQ

  • @user-du8yk6eh5u
    @user-du8yk6eh5u2 жыл бұрын

    Как всё работает понятно. Но зачем нужен wrapper? Если этот же код прописать во внешней функции test_time всё будет работать точно также. Каким образом используется замыкание?

  • @selfedu_rus

    @selfedu_rus

    2 жыл бұрын

    вы тогда не сможете передавать аргументы функции (без wrapper), точнее передать только один раз

  • @nilmulyashov7274

    @nilmulyashov7274

    2 жыл бұрын

    Ютуб не пропускает слишком большой коммент, так что буду частями) К примеру, у нас есть вот такие функции: def list_by_cycle(): lst = [] for i in range(100): if i % 2 == 0: lst.append(i) return lst def list_comprehension(): lst = [i for i in range(100) if i % 2 == 0] return lst И мы хотим посчитать их время работы, чтоб сравнить, какая быстрее. Это можно сделать так: import time def list_by_cycle(): start = time.perf_counter() # Замеряем время до отработки функции lst = [] for i in range(100): if i % 2 == 0: lst.append(i) return lst def list_comprehension(): start = time.perf_counter() # Замеряем время до отработки функции lst = [i for i in range(100) if i % 2 == 0] print(time.perf_counter() - start) # Считаем, за сколько отработала функция return lst

  • @nilmulyashov7274

    @nilmulyashov7274

    2 жыл бұрын

    Но при такой записи мы нарушим принцип единой ответственности функций и принцип DRY. Вынесем всю логику со временем в отдельную функцию. Получится вот это: import time def wrapper(func): start = time.perf_counter() # Замеряем время до отработки функции res = func() print(time.perf_counter() - start) # Считаем, за сколько отработала функция return res def list_by_cycle(): lst = [] for i in range(100): if i % 2 == 0: lst.append(i) return lst def list_comprehension(): lst = [i for i in range(100) if i % 2 == 0] return lst Тогда мы сможем обернуть наши функции в функцию wrapper вот так: # распечатает только время работы функций wrapper(list_by_cycle) wrapper(list_comprehension) # либо так: # распечатает время работы функций и сам сгенерированный список print(wrapper(list_by_cycle)) print(wrapper(list_comprehension))

  • @nilmulyashov7274

    @nilmulyashov7274

    2 жыл бұрын

    Пока все ок. Так можно. НО! Что если у функций теперь появятся аргументы? Допустим, я хочу сам задавать диапазон в range. Тогда код функций будет выглядеть вот так: def list_by_cycle(n): lst = [] for i in range(n): if i % 2 == 0: lst.append(i) return lst def list_comprehension(n): lst = [i for i in range(n) if i % 2 == 0] return lst Как быть с функцией wrapper? Ну, сходу напрашивается вот такой вариант (причем, в общем случае придется написать **kwargs вместо n): def wrapper(func, n): start = time.perf_counter() # Замеряем время до отработки функции res = func(n) print(time.perf_counter() - start) # Считаем, за сколько отработала функция return res Поэтому, когда будем делать обертку (т.е. при вызове wrapper), придется передавать туда дополнительный аргумент, и будет уже вот это: # распечатает только время работы функций wrapper(list_by_cycle, n=100) wrapper(list_comprehension, n=100) # либо так: # распечатает время работы функций и сам сгенерированный список print(wrapper(list_by_cycle, n=100)) print(wrapper(list_comprehension, n=100))

  • @nilmulyashov7274

    @nilmulyashov7274

    2 жыл бұрын

    А теперь, что если мы захотим сохранять сгенерированные списки в переменные? Можно сделать так: list_by_cycle_r100 = wrapper(list_by_cycle, n=100) list_comprehension_r100 = wrapper(list_comprehension, n=100) А теперь, что если мне нужно несколько списков в разных диапазонах? Как поступим? Если в лоб делать, то получится вот это: list_by_cycle_r100 = wrapper(list_by_cycle, n=100) list_comprehension_r100 = wrapper(list_comprehension, n=100) list_by_cycle_r1000 = wrapper(list_by_cycle, n=1000) list_comprehension_r1000 = wrapper(list_comprehension, n=1000) list_by_cycle_r10000 = wrapper(list_by_cycle, n=10000) list_comprehension_r10000 = wrapper(list_comprehension, n=10000) Что в итоге-то? Для каждого нового диапазона приходится постоянно оборачивать целевую функцию (т.е. постоянно вызывать wrapper, опять нарушение принципа DRY) и плодить новые переменные. Было бы гораздо удобнее, если бы был синтаксис, позволяющий написать сразу вот так (формируем идеальный конечный результат, так сказать): list_by_cycle_r100 = list_by_cycle(n=100) list_by_cycle_r1000 = list_by_cycle(n=1000) list_by_cycle_r10000 = list_by_cycle(n=10000) Т.е. чтоб функция работала, как и раньше, но при этом еще и время считалось. Было бы вообще здорово. При этом код целевых функций не меняем - помним про принцип единой ответственности. Что ж, на ум приходит вот такая реализация (обратите внимание - мы хотим вызвать wrapper лишь один раз в самом начале): list_by_cycle = wrapper(list_by_cycle) list_comprehension = wrapper(list_comprehension)

  • @user-jh3xl2ij3r
    @user-jh3xl2ij3r2 жыл бұрын

    Видео за 13 минут, разбираюсь что происходит три часа((

  • @user-qk3ey6tb1k
    @user-qk3ey6tb1k2 жыл бұрын

    неужели темная тема

  • @gore_ot_uma166
    @gore_ot_uma1662 жыл бұрын

    а есть декоратор, который удаляет все декораторы с какой-либо декорированной функции? ведь не всегда нужен функционал декоратора

  • @selfedu_rus

    @selfedu_rus

    2 жыл бұрын

    оставляете ссылку на прежнюю функцию, а декоратор на другую переменную, когда она будет не нужна, то сборщик мусора автоматически удалит декоратор, а функция останется как была

  • @gore_ot_uma166

    @gore_ot_uma166

    2 жыл бұрын

    Не понял, как это сделать? Есть код: @декоратор Def Функция(): pass Как вызвать эту функцию без декоратора, если он нам в данный момент не нужен?

  • @selfedu_rus

    @selfedu_rus

    2 жыл бұрын

    @@gore_ot_uma166 так вы декоратор применяйте через функцию: a = декоратор(Функция)

  • @gore_ot_uma166

    @gore_ot_uma166

    2 жыл бұрын

    Спасибо, тоже думал про этот вариант.

  • @user-el1fy2ob4d
    @user-el1fy2ob4d Жыл бұрын

    Не совсем понимаю, для чего вообще внутри func_decorator объявляется еще функция wrapper. Почему нельзя просто в func_decorator: что-то делаем до, func(), что-то делаем после

  • @selfedu_rus

    @selfedu_rus

    Жыл бұрын

    wrapper как раз и подменяет прежнюю функцию, добавляя некоторый функционал, без этого декораторы в принципе не работали бы (или было бы просто вызов одной функции через другую в лоб, передавая каждый раз ссылку на функцию + аргументы)

  • @user-el1fy2ob4d

    @user-el1fy2ob4d

    Жыл бұрын

    @@selfedu_rus Спасибо. Кажется немного поняла, посмотрев еще следующее видео.

  • @ney107-iz6xl
    @ney107-iz6xl7 ай бұрын

    Я декораторы и замыкания понял Тому кто не понял пересмотрите материал возобновите в голове и вернитесь сюда я конечно не весь материал а то что чуть-чуть не поняли или забыли

  • @user-rq2ob4is5e
    @user-rq2ob4is5e Жыл бұрын

    А зачем делать вложенную функцию?? в чем разница такого кода и def func1(func): делаем что то перд func func() делаем что то после func

  • @selfedu_rus

    @selfedu_rus

    Жыл бұрын

    А как вы этой функции будете передавать аргументы? Каждый раз вызывать func1 с первым параметром func? Это не очень красивое решение.

  • @mrpjetrov378
    @mrpjetrov378 Жыл бұрын

    Всем пока, я на завод

  • @olegbaskakov3399
    @olegbaskakov33992 жыл бұрын

    Непонятно, зачем нужен wrapper, если и без него весь код можно поместить в func_decorator(func) и вызывать ее самостоятельно.

  • @selfedu_rus

    @selfedu_rus

    2 жыл бұрын

    вы тогда не сможете декорировать разные функции

  • @user-du8yk6eh5u

    @user-du8yk6eh5u

    2 жыл бұрын

    @@selfedu_rus Сергей, я извиняюсь, но всё равно не понятно - в примере функция test_time вызывается последовательно для медленного алгоритма и для быстрого. Если бы у test_time не было wrapper и весь код по замеру времени был написан непосредственно в test_time то все будет работать аналогично. Я проверил) Поэтому смысл wrapper не понятен.

  • @nilmulyashov7274

    @nilmulyashov7274

    2 жыл бұрын

    Я тоже задался этим вопросом. Ответил выше.

  • @user-kf7hv6nm2s
    @user-kf7hv6nm2s8 ай бұрын

    Этот учитель не понятно объясняет, замудренным языком,Я не понимаю что вы от него так балдеете, может мусолин постоянно

  • @tbassir9076
    @tbassir9076 Жыл бұрын

    Да, сложновато, но понятно, особенно в конце. Вы всё разложили по полочкам, а в конечном итоге главное оказалось @test_time

  • @illiukhin
    @illiukhin2 жыл бұрын

    спасибо