Уроки Python casts #6 - Декораторы
ฝัง
- เผยแพร่เมื่อ 2 มิ.ย. 2018
- Мои курсы:
Boosty:
boosty.to/omolchanov/posts/99...
Patreon:
/ karty-vsekh-41011404
Что такое декораторы в Python, для чего они нужны, как их писать и в каких случаях использовать. Рассматриваем три варианта использования:
1. Декорируем функцию, не принимающую аргументов
2. Декорируем функцию, принимающую аргументы
3. И функция и декоратор принимают аргументы
** ИСХОДНЫЙ КОД **
Основных проектов доступен в Patreon:
/ iskhodnyi-kod-26640469
***
------
🔷 Для донатов. Всегда очень признателен за это:
www.donationalerts.ru/r/omolc...
------
Продолжение серии уроков по языку Python для начинающих. Серия посвящена отдельным темам по программированию на Python.
★ Важно:
Как читать Traceback Python:
• Как читать Traceback P...
Работа с ошибками на примере двух нерабочих парсеров:
• Python: работа с ошибк...
★ Все серии Python casts:
1 - Что вам нужно знать о Pip
• Уроки Python Casts # 1...
2 - Переменные окружения. Использование.
• Уроки Python casts # 2...
3 - Что означает *args, **kwargs
• Уроки Python casts # 3...
#4 - if __name __ == '__main__': что это значит
• Уроки Python casts #4 ...
#5 - Генераторы списков (List comprehension)
• Уроки Python casts #5 ...
#6 - Декораторы
• Уроки Python casts #6 ...
#7 - 5 приемов, о которых вы могли не знать
• Уроки Python casts #7 ...
#8 - Замыкания
• Уроки Python casts #8 ...
#9 - Что такое try... except...
• Уроки Python casts #9 ...
#10 - Что такое yield
• Уроки Python casts #10...
#11 - Как работает функция map()
• Уроки Python casts #11...
#12 - Как работает функция filter()
• Уроки Python casts #12...
#13 - Else у циклов For и While
• Уроки Python casts #13...
★ Плейлисты:
Django 2.x:
• Уроки Django 2.x
Flask:
• Создание блога на Flas...
Боты для Телеграма:
• Telegram боты на Python
Работа с API Вконтакте:
• Работа с API Вконтакте...
Мне 63. Хотел учиться веб-дизайну, но через год понял, что до заработка мой левел в этой жизни уже не поднимется. Теперь занимаюсь чисто для борьбы с альт-геймером ) Так вот, как раз вчера, преодолевая невероятное сопротивление нейронов, заставил их законтачить на понятии Декоратора. На эту СОБАКУ (@) у меня ушёл весь день! А сегодня, слушая Ваше изложение, удивлялся тому, что можно сложные вещи объяснить ПРОСТО! У Вас - БЕЗУПРЕЧНОЕ изложение материала. Я даже не помню, когда я так радовался речи преподавателя!! Грейт грейтфул Вам !! ))
Спасибо большое. Очень рад, что мой контент вам помог
Не боись дед! Все получится! И в 73 года учатся и устраиваются прогерами. А раз уж ты тут(на ютубе) , загугли про это и все поймешь
Мое уважение.
Дерзайте. Мой папа в 70 лет программировать научился ! На Visual basic
@@zaemiel а получается def timeit это обычная функция? И выходит любую функцию можно вызвать собакой?
Или что-то делает def timeit не функцией, а именно декоратором?
Удивительно ! Лучшее объяснение, которое я встречала, у вас талант объяснять, спасибо)
Порадовал ход твоих мыслей. Люблю когда мысли хронологично опираются друг на друга, создавая правильную логичную последовательность, без темных кусков и взятых неоткуда сущностей. СПАСИБО тебе, амиго, ты один из лучших.
Автору огромное спасибо, вот сейчас стало понятно крайне доходчиво, зачем нужны Декораторы, чтобы не было лишнего кода помимо основного кода в теле функции!!
Там в конце было сказано: "если понравилось - подписывайтесь на канал и ставьте лайки".
Понравилось?
Да это не то слово! Я в восторге просто! Большое спасибо!
я не понимал,что такое декоративы, но с помощью тебя я понял все. Спасибо!
Олег,спасибо за Ваш труд , Вам удалось с такой лёгкостью донести такую непростую тему..Вы один из лучших преподавателей , которых я встречал !
Вот это годнота.
Я и до этого с декораторами работал, но не понимал их применение и использовал чуть по-другому.
Спасибо! Приятно когда объясняет тему не просто человек который знает сам, но и который именно умеет объяснять! Редкость!
Олег, как же приятно Вас слушать. Объяснение выше всяких похвал!
Все грамотно и информативно разложено по полочкам. Большое спасибо за Ваш труд!
Спасибо, Олег! Отличные уроки у Вас! Продолжайте в том же духе.
Олег, спасибо огромное за такое разжевывание темы. Ты такие моменты затрагиваешь, которые непонятны интуитивно при изучении, да и к тому, их и сформулировать как вопрос сложно. А ты это объясняешь всё...Респект тебе!
Бог программирования, спасибо большое, за доступное и наглядное объяснение!
Спасибо Олег! Ваши видео очень полезны для расширения понимания материала
Спасибо за понятное объяснение на пальцах!
Дякую. Світлий розум і відкрите серце дають вам змогу бути гарним вчителем. Це рідкісний дар.
Привет!
Всегда воспринимал декораторы как нечто сложное, но благодаря тебе с легкостью разобрался
Огромное спасибо за этот урок и все остальные!
Спасибо, наконец я понял как они работают и для чего нужны эти декораторы 👍
Самое Доходчивое объяснение материала!
Большое спасибо, очень приятное и подробное объяснение!
Шикарная демонстрация замыканий, огромный респект! и Вот я уже на декораторах)
Очень круто! Спасибо за объяснение!
Отличное изложение! Пример то что надо! Смотрел другие видосы про декораторы, читал. На таких кривых примерах объяснялось всё, что не понятно было для чего городить огород. Спасибо!
Спасибо вам, самый доступный подход к объяснению!
Очень внятное и доступное объяснение роли декораторов! Жаль, что Вас на степике нет.
Спасибо ваша лекция сильно помогла!
Спасибо Олег, вы лучший преподаватель!
Отличное и доступное обьяснение. Спасибо!
очень хорошие касты по python! Подписался )
Мужик, я бы тебе дал) Заплатил бабки за курс, а учат меня такие интузиасты как ты, спасибо!
Oleg восхищаюсь упорством… не прекращай создавать контент
Олег, спасибо! Теперь то все понятно наконец =) Я уже не первый десяток видео про декораторы смотрю, твое будет последним, ибо после него вопросов не остается совсем)
Круто объясняете, всё понятно, спасибо!
я в шоке! Наконец-то понял как это работает! Такого простого объяснения я не ожидал. Спасибо!
Олег, спасибо, очень понятно объясняешь
лучшее объяснение про декораторы!
Один из самых полезных каналов
Поскольку l1 = результат ВЫПОЛНЕНИЯ функции timeit, а результат выполнения этой функции = return wrapper, то в итоге, l1 = wrapper (то, что вернуло выполнение функции timeit). Спасибо за это пояснение! Никак не мог понять почему так происходит)
Спасибо. Доступно изложено
Класс! Все просто и понятно!
Очень понятно рассказано, спасибо!
Олег, спасибо большое!
Спасибо большое! очень понятно, а то читал в паре мест, смотрел в курсах - там плохо было рассказано.
ПФ ... Мужик.... Здоровья тебе, хахаха, ибо я столько стучался, что бы понять как работает декоратор, а ты нормально объяснил всё на адекватных примерах. Спасибо огромное
Три дня разбираюсь с декораторами. И только из этого видео понял, что это за зверь!)
Спасибо, очень доходчиво объясняете
Отличное объяснение, спасибо вам
Олег, большое спасибо.
Как вариант, более короткая форма для парных чисел используя range:
>>> l = [x for x in range(2,100,2)]
>>> print(l)
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98]
или l = [x*2 for x in range(1, 500)]
Здесь я думаю специально "поддали нагрузки", проводя сравнения остатка с нулем.
Да, этот алгоритм покруче
Спасибо, да да и про замыкания. Пожалуйста.
интересно, понятно) спасибо!
я 5 лет пытался понять что это, а автор этого урока расказал за 7 минут
Капец!!! перелопатил кучу документации - не понял... тут за 15 мин всё ясно!!! СПС
Спасибо!
Спасибо большое за контент, единствеенное, если заглянуть глубоко получается, что декораторы это частные случаи замыканий.
Возможно стоило сначала рассказать о замыканиях а потом уже о декораторах.
Блестяще!!!
Круто
Круто
И ещё раз
Круто!
Спасибо!
Спасибо. Я понял что такое декораторы
шикарная архитектура Python ,,,, ох я счастлив ! Истина со мной
Из двух других видеоуроков с горем пополам понял, что такое декораторы, но совершенно не понял их предназначение - муть какая-то. Уже думал, что на этой теме мои способности иссякают, но погуглил и попал сюда - тут всё понятно сразу же, тк что это не у меня способности иссякают, а спсобность объяснять - у тех преподов, которых смотрел. Большое спасибо!
Расскажи про yeild и магические методы
Занятный момент - код внутри декоратора на самом верхнем уровне будет выполнен всегда, при инициализации декорируемой функции (на чём собственно и основана работа маршрутизатора упомянутого Flask), это видно при запуске скрипта - вызовов функций нет, но вывод идёт. Было бы здорово акцентировать на этом внимание и дополнить примерами использования. Может даже на отдельный выпуск хватить )
PS: Я ещё не всё посмотрел, может это в другом видео есть, но вдруг )
нет, я на этом не акцентировался. Наверное, действительно следовало об этом сказать...
Для тех кто столкнулся с подобным вопросом, но самостоятельно не может найти на него ответа, вот отличная статья на хабре habr.com/ru/post/141501/
Спасибище!
Лучший!
Благодрю.
Ну это крутоо )
Спасибо!!!
Спасибо, отличный автор, приятно слушать и смотреть.
Спасибо
крутой чувак)
_Олег, привет. У тебя замечательные уроки получаются. Очень толково и грамотно объясняешь. А не планируешь ли ты записать полноценный обучающий курс по Python? Прям чтоб с азов (для начинающих) до вершин мастерства?_
Можешь воспользоваться этими курсами:
этот для начала stepik.org/course/67
этот сложнее stepik.org/course/512
этот самый сложный stepik.org/course/1280
Поддерживаю на все 100%
_спасибо за ссылки, Марк, но этих ребят я не знаю, а вот Олег себя отлично поставил. Потому и обращаюсь к нему_
Роман Белов присоединяюсь. С удовольствием записался бы.
Роман Белов было бы круто
офигенный пример с datetime
я бы добавил сюда что для того, чтобы декорируемая функция при вызове __name__ возвращала свое имя, нужно wrapper в свою очередь декорировать @functools.wraps(func) из стандартной библиотеки functools, это не обязательно, но бывает очень полезно например при выводе ошибки или при отладке программы
from flask import session
from functools import wraps # standart decorator for selfmade decorators
def check_logged_in(func: 'object') -> 'object':
@wraps(func)
def wrapper(*args, **kwargs):
if 'logged_in' in session:
return func(*args, **kwargs)
return 'You are NOT logged in.'
return wrapper
я вообще декораторами записываю трейсбеки в базу с именем фунции всеми аргументами, если интересно сделаю ссылку на код. чтою велосипед не изобретать
@@TahirKabilov давай
Спасибо
12:00 генератор отработал медленнее) думаю, дело в том, что генератор сразу резервирует место, а при вызове метода append() иногда приходится переносить весь список в новую область памяти.
годнота
Просто обязана отписаться, что разжевано действительно восхитительно, спасибо от всей души!
Здравствуйте. На 15:40, если я всё правильно понял, то это синтаксический сахар не для l1 = timeit(one), а для замены one = timeit(one)? На 17:20 получается, что код между timeit и outer будет выполнен уже на этапе декорирования, т.е. ещё до вызова декорируемой функции? Если да, то не очень понятно для чего это нужно.
лайк, Олег
не сказал только, что вместо 'args' и 'kwargs' мы можем написать любые другие идентификаторы (имена), хоть 'parampam1' и 'parampam2', - это НЕ специмена (или какие-то операторы языка), а просто договорились так называть эти параметры в подобных случаях - а вообще это просто параметры, которые можно назвать как угодно (главное - поставить зведочки '*' и '**").
трудно понять зачем объяснять, тем для кого это ну очень очевидно (тебе), но новичков это реально путает и вымораживает:
что такое 'args', что такое 'kwargs' (это особенно страшное слово), и почему они везде.
а это просто название от балды двух параметров, и сокращение от фраз 'arguments' и 'keyword arguments'.
они прям реально на этом месте запинаются, как минимум, и долго (до полугода) постоянно возвращаются к этому, как максимум.
это резко углубит объяснение, в то же время не усложняя его. возможно, ты заострял внимание на этом моменте в каком-то другом ролике
0:20 пример, в котором следует использовать декораторы
7:21 о функциях как объектах
7:58 декоратор функции, не принимающей аргументы
10:46 добавление аргументов в функцию
12:07 как работает синтаксический сахар @decorator
15:49 добавление аргументов декоратора
Прикольно, что на 11:56 время создания списка через for меньше, чем через генератор. Понятно, что это погрешность, но всё же)
Я кстати это тоже заметил. Вообще как только он обернул всё в декоратор, то почему-то скорость у for значительно возросла. А когда он сменил 10**4 на 10000, так вот for ещё и вышел в лидеры по скорости.
@@devZu9 предполагаю, потому что в цикле 10**4 считалось снова и снова каждую итерацию, а в той конструкции результат запоминался
офигеть
Олег, добрый день. Сможете подсказать логику Питона исходя из следующего кода:
Код стоит считать бессмысленным.
Была просто практика с декораторами.
def PlusN(func):
def wrapper(n):
print('1', n)
n += 2
print('2', n)
result = func(n)
return wrapper
@PlusN
def CountN(n):
print('3', n)
print(n ** 2)
#CountN(3)
wrap = PlusN(CountN)
print(wrap)
countN = wrap(3)
Вопрос в том, что на выходе ответ будет 49.
Я понимаю, что питон вызывает 2 раза wrapper. Но при этом только 1 раз CountN.
Если декоратор закомментить, то будет ожидаемая цифра 25.
Спасибо.
Спасибо за Ваши видео, как всегда всё на высоте ! Не совсем понял, зачем в функцию wrapper вы принимаете *args и **kwargs, ведь если эта функция получить кортеж или словарь, то будет ошибка, или я чего не понимаю ?
*args и **kwargs - это не просто список или словарь - это позиционные и именованные аргументы.
Экспериментируйте и посмотрите, какие аргументы и куда идут на вход...
Ну не знай на счет скорости, порой происходит обратное. Возможно что-то изменили в Python на 2020 год, может погрешности или прирост только в Linux, но особой разницы не видно, по крайней мере на Windows.
Разница колеблется в районе 0:00:00.000010
Вот некоторое количество результатов:
one: 0:00:00.001000
two: 0:00:00.000999
-----------------------------------------
one: 0:00:00.001004
two: 0:00:00.000999
-----------------------------------------
one: 0:00:00.001007
two: 0:00:00.000998
-----------------------------------------
one: 0:00:00.000999
two: 0:00:00.000999
-----------------------------------------
one: 0:00:00.000999
two: 0:00:00.001000
Возможно при сильно нагруженных проектах это пройдет, но на легких точно разницы нет. Возможно я чего-то не понимаю.
Как много всего возможного в этом сообщении =)
добрый день. Почему нельзя в предпоследний return(который перед return wrapper стоит в функции timeit) вставить func(*args,**kwargs) сразу? Так работает быстрее
13:18, можно просто:
l1 = one
print(l1(10))
красава. монстр.
@@johnwoods978 print(one(10))
ПРОСТО МАШИНА
Олег, Вы говорите не про генераторы, а про list comprehension. Можно создавать генераторы подобным способом, но скобки должны быть круглые, например: g = (x for x in range(10**4) if x % 2 == 0)
Честно говоря, даже не представляю чем вы слушаете....
Здесь я говорю только о генераторах списков.
0:18 - впервые упоминаю генератор списка
0:36 - уже второе упоминание
0:57 - третье при постановке задачи
И минуты не прошло, как генераторы списков были упомянуты мной трижды.
Этот скринкаст находится в контексте предыдущего, который и был целиком посвящен генераторам списков - list comprehension.
Для удобства Марк сократил в своем коменте упоминание - до генераторов, потому что мы находились в определенном контексте, который нужно учитывать. Об этом я тоже сказал.
А так да - то, что вы написали - это генератор.
Видимо я просто привык к другой терминологии, мне помниться, это называли списковое включение, в вики есть одноименная статья. В любом случае, Вы делаете хорошие уроки, продолжайте в том же духе!
Спасибо. Прошу прощения за резкость.
Take a like from the beginning))
Отличный урок. Единственное что я так и не понял - почему в конце урока, когда добавлена функция outer, аргумент name выводится в консоль два раза (команда print в 7-й строке) ? Когда происходит второе обращение к этой функции print ?
удалось разобраться?
11:54 при запуске видно, что второй вызов происходит дольше чем первый :)
я пишу в пайчарме и самое смешное это то, что время разное выдает, иногда генератор быстрее, иногда медленее
[x for x in range(10**9) if x % 3 == 0] >>> Memory Error =) (P.S. Надо больше оперативки? )
на 9.42 м. запустил у себя. Получил TypeError: 'list' object is not callable. Когда привел к виду l1 = one
l2 = two (без скобок) заработало без ошибок. Вопрос, что это было?
Объяснение - огнище. А то один и тот же пример у большинства - с числами Фибоначчи. На кой черт мне городить огород ради такого, где мне в реальности использовать? А тут все объяснения "реального мира": нарушает принципы dry и единой ответственности, да ещё и объяснение без использования сахара. Короче, от души!
Это не касается данного урока, но в этих конкретных примерах оптимальнее было бы убрать control flow statement используя третий аргумент "step" в функции range.
even = [num for num in range(0, 10**4, 2)]
а почему при указании func в скобках вызывалась именно функция one, а не two?
А почему после использования декораторов время выполнения с циклом уменьшилось? Кеширование?
Обратите внимание что скорость выполнения увеличивается ровно в два раза. Так что если нужна скорость декораторы ее только замедлят.
на 12й секунде, функция two неожиданно стала дольше работать! Тогда как ранее была быстрее чем one. Из-за чего?