Уроки 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 восхищаюсь упорством… не прекращай создавать контент
Отличное объяснение, спасибо вам
Как вариант, более короткая форма для парных чисел используя 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)]
Здесь я думаю специально "поддали нагрузки", проводя сравнения остатка с нулем.
Да, этот алгоритм покруче
Капец!!! перелопатил кучу документации - не понял... тут за 15 мин всё ясно!!! СПС
Отличное изложение! Пример то что надо! Смотрел другие видосы про декораторы, читал. На таких кривых примерах объяснялось всё, что не понятно было для чего городить огород. Спасибо!
Спасибо, да да и про замыкания. Пожалуйста.
я в шоке! Наконец-то понял как это работает! Такого простого объяснения я не ожидал. Спасибо!
Олег, спасибо! Теперь то все понятно наконец =) Я уже не первый десяток видео про декораторы смотрю, твое будет последним, ибо после него вопросов не остается совсем)
интересно, понятно) спасибо!
Спасибо!
Поскольку l1 = результат ВЫПОЛНЕНИЯ функции timeit, а результат выполнения этой функции = return wrapper, то в итоге, l1 = wrapper (то, что вернуло выполнение функции timeit). Спасибо за это пояснение! Никак не мог понять почему так происходит)
Три дня разбираюсь с декораторами. И только из этого видео понял, что это за зверь!)
ПФ ... Мужик.... Здоровья тебе, хахаха, ибо я столько стучался, что бы понять как работает декоратор, а ты нормально объяснил всё на адекватных примерах. Спасибо огромное
офигенный пример с datetime
Спасибо большое! очень понятно, а то читал в паре мест, смотрел в курсах - там плохо было рассказано.
я 5 лет пытался понять что это, а автор этого урока расказал за 7 минут
Блестяще!!!
Круто
Круто
И ещё раз
Круто!
Спасибо!
Спасибо большое за контент, единствеенное, если заглянуть глубоко получается, что декораторы это частные случаи замыканий.
Возможно стоило сначала рассказать о замыканиях а потом уже о декораторах.
Лучший!
Спасибо. Я понял что такое декораторы
шикарная архитектура Python ,,,, ох я счастлив ! Истина со мной
Спасибище!
Расскажи про yeild и магические методы
Благодрю.
Из двух других видеоуроков с горем пополам понял, что такое декораторы, но совершенно не понял их предназначение - муть какая-то. Уже думал, что на этой теме мои способности иссякают, но погуглил и попал сюда - тут всё понятно сразу же, тк что это не у меня способности иссякают, а спсобность объяснять - у тех преподов, которых смотрел. Большое спасибо!
Спасибо, отличный автор, приятно слушать и смотреть.
Спасибо
Спасибо!!!
крутой чувак)
Ну это крутоо )
Спасибо
лайк, Олег
не сказал только, что вместо 'args' и 'kwargs' мы можем написать любые другие идентификаторы (имена), хоть 'parampam1' и 'parampam2', - это НЕ специмена (или какие-то операторы языка), а просто договорились так называть эти параметры в подобных случаях - а вообще это просто параметры, которые можно назвать как угодно (главное - поставить зведочки '*' и '**").
трудно понять зачем объяснять, тем для кого это ну очень очевидно (тебе), но новичков это реально путает и вымораживает:
что такое 'args', что такое 'kwargs' (это особенно страшное слово), и почему они везде.
а это просто название от балды двух параметров, и сокращение от фраз 'arguments' и 'keyword arguments'.
они прям реально на этом месте запинаются, как минимум, и долго (до полугода) постоянно возвращаются к этому, как максимум.
это резко углубит объяснение, в то же время не усложняя его. возможно, ты заострял внимание на этом моменте в каком-то другом ролике
Занятный момент - код внутри декоратора на самом верхнем уровне будет выполнен всегда, при инициализации декорируемой функции (на чём собственно и основана работа маршрутизатора упомянутого Flask), это видно при запуске скрипта - вызовов функций нет, но вывод идёт. Было бы здорово акцентировать на этом внимание и дополнить примерами использования. Может даже на отдельный выпуск хватить )
PS: Я ещё не всё посмотрел, может это в другом видео есть, но вдруг )
нет, я на этом не акцентировался. Наверное, действительно следовало об этом сказать...
Для тех кто столкнулся с подобным вопросом, но самостоятельно не может найти на него ответа, вот отличная статья на хабре habr.com/ru/post/141501/
_Олег, привет. У тебя замечательные уроки получаются. Очень толково и грамотно объясняешь. А не планируешь ли ты записать полноценный обучающий курс по Python? Прям чтоб с азов (для начинающих) до вершин мастерства?_
Можешь воспользоваться этими курсами:
этот для начала stepik.org/course/67
этот сложнее stepik.org/course/512
этот самый сложный stepik.org/course/1280
Поддерживаю на все 100%
_спасибо за ссылки, Марк, но этих ребят я не знаю, а вот Олег себя отлично поставил. Потому и обращаюсь к нему_
Роман Белов присоединяюсь. С удовольствием записался бы.
Роман Белов было бы круто
0:20 пример, в котором следует использовать декораторы
7:21 о функциях как объектах
7:58 декоратор функции, не принимающей аргументы
10:46 добавление аргументов в функцию
12:07 как работает синтаксический сахар @decorator
15:49 добавление аргументов декоратора
годнота
Здравствуйте. На 15:40, если я всё правильно понял, то это синтаксический сахар не для l1 = timeit(one), а для замены one = timeit(one)? На 17:20 получается, что код между timeit и outer будет выполнен уже на этапе декорирования, т.е. ещё до вызова декорируемой функции? Если да, то не очень понятно для чего это нужно.
Объяснение - огнище. А то один и тот же пример у большинства - с числами Фибоначчи. На кой черт мне городить огород ради такого, где мне в реальности использовать? А тут все объяснения "реального мира": нарушает принципы dry и единой ответственности, да ещё и объяснение без использования сахара. Короче, от души!
я бы добавил сюда что для того, чтобы декорируемая функция при вызове __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() иногда приходится переносить весь список в новую область памяти.
офигеть
я пишу в пайчарме и самое смешное это то, что время разное выдает, иногда генератор быстрее, иногда медленее
Просто обязана отписаться, что разжевано действительно восхитительно, спасибо от всей души!
Спасибо за Ваши видео, как всегда всё на высоте ! Не совсем понял, зачем в функцию wrapper вы принимаете *args и **kwargs, ведь если эта функция получить кортеж или словарь, то будет ошибка, или я чего не понимаю ?
*args и **kwargs - это не просто список или словарь - это позиционные и именованные аргументы.
Экспериментируйте и посмотрите, какие аргументы и куда идут на вход...
11:54 при запуске видно, что второй вызов происходит дольше чем первый :)
Прикольно, что на 11:56 время создания списка через for меньше, чем через генератор. Понятно, что это погрешность, но всё же)
Я кстати это тоже заметил. Вообще как только он обернул всё в декоратор, то почему-то скорость у for значительно возросла. А когда он сменил 10**4 на 10000, так вот for ещё и вышел в лидеры по скорости.
@@devZu9 предполагаю, потому что в цикле 10**4 считалось снова и снова каждую итерацию, а в той конструкции результат запоминался
Отличный урок. Единственное что я так и не понял - почему в конце урока, когда добавлена функция outer, аргумент name выводится в консоль два раза (команда print в 7-й строке) ? Когда происходит второе обращение к этой функции print ?
удалось разобраться?
на 9.42 м. запустил у себя. Получил TypeError: 'list' object is not callable. Когда привел к виду l1 = one
l2 = two (без скобок) заработало без ошибок. Вопрос, что это было?
Олег, добрый день. Сможете подсказать логику Питона исходя из следующего кода:
Код стоит считать бессмысленным.
Была просто практика с декораторами.
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.
Спасибо.
добрый день. Почему нельзя в предпоследний return(который перед return wrapper стоит в функции timeit) вставить func(*args,**kwargs) сразу? Так работает быстрее
Олег, Вы говорите не про генераторы, а про list comprehension. Можно создавать генераторы подобным способом, но скобки должны быть круглые, например: g = (x for x in range(10**4) if x % 2 == 0)
Честно говоря, даже не представляю чем вы слушаете....
Здесь я говорю только о генераторах списков.
0:18 - впервые упоминаю генератор списка
0:36 - уже второе упоминание
0:57 - третье при постановке задачи
И минуты не прошло, как генераторы списков были упомянуты мной трижды.
Этот скринкаст находится в контексте предыдущего, который и был целиком посвящен генераторам списков - list comprehension.
Для удобства Марк сократил в своем коменте упоминание - до генераторов, потому что мы находились в определенном контексте, который нужно учитывать. Об этом я тоже сказал.
А так да - то, что вы написали - это генератор.
Видимо я просто привык к другой терминологии, мне помниться, это называли списковое включение, в вики есть одноименная статья. В любом случае, Вы делаете хорошие уроки, продолжайте в том же духе!
Спасибо. Прошу прощения за резкость.
а почему при указании func в скобках вызывалась именно функция one, а не two?
А почему после использования декораторов время выполнения с циклом уменьшилось? Кеширование?
Повторил эксперимент. Для последовательности 10**8 списочный генератор срабатывает на полсекунды медленнее в 6 из 7 случаев
13:18, можно просто:
l1 = one
print(l1(10))
красава. монстр.
@@johnwoods978 print(one(10))
ПРОСТО МАШИНА
Ну не знай на счет скорости, порой происходит обратное. Возможно что-то изменили в 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
Возможно при сильно нагруженных проектах это пройдет, но на легких точно разницы нет. Возможно я чего-то не понимаю.
Как много всего возможного в этом сообщении =)
Это не касается данного урока, но в этих конкретных примерах оптимальнее было бы убрать control flow statement используя третий аргумент "step" в функции range.
even = [num for num in range(0, 10**4, 2)]
Безусловно, всё хорошо. Но тема капец сложная, даже с всеми этими объяснениями я не смог нормально понять как делать эти декораторы. Но понять для чего они хотя бы удалось. В любом случае спасибо за потраченное время и удачи в следующих роликах
а что конкретно непонятно? Я разобрался, если что могу помочь объяснить
Спасибо, но а код где ?
Take a like from the beginning))