Я думаю, если бы в школах платили такую же зарплату, что получают только очень хорошие программисты, то Сергей был бы там учителем. А свой собственный курс на степике, был бы неплохой добавкой к этой зарплате. Сейчас профессию учителя просто втоптали в грязь. А ведь ее важность не меньше, чем у какого-нибудь врача. Врач жизни спасает. А чтобы стать хорошим врачом - надо выучиться. Хреновый учитель, даже будущего гения так отворожит от своего предмета, что тот до конца жизни будет считать себя бездарем в этой теме.
Выглядит намного красивее и компактнее, чем обычный вариант с вложенными функциями! Особенно в случае с декоратором с параметрами, где 3 функции вложены друг в друга
#43. Области видимости переменных. Ключевые слова global и nonlocal | Python для начинающих ruclips.net/video/TacyWpUF1Kk/видео.html #44. Замыкания в Python | Python для начинающих ruclips.net/video/sJF7OMNgLUs/видео.html #45. Введение в декораторы функций | Python для начинающих ruclips.net/video/v0qZPplzwUQ/видео.html #46. Декораторы с параметрами. Сохранение свойств декорируемых функций | Python для начинающих ruclips.net/video/bl_CnIVpWmQ/видео.html
Сергей,спасибо большое за урок,но заметил такую штуку,что в следующем уроке вы более понятно обьяснили я посмотрел про str,repr,len,abs,а потом снова посмотрел этот урок и понял))
Супер)) Спасибо большое, Сергей) ещё бы обещанный Синглтон через _call_ и _new_ и будет счастье), самостоятельно я в тупике _ нужна помощь !!!! Тоже очень интересует этот вопрос
Самое ценное в этом уроке - вспомнил что такое производная). Немного отвлекся, освежил эту, благополучно забытую, математическую тему. Еще бы уяснить разницу между производной функции и дифферениалом. По мне, сейчас, так это одно и то же. Огромное спасибо Сергею Михайловичу! Изучаю Python пока в качестве хобби. Пробегаю по быстрому оба курса - начальный и ООП. Знакомлюсь пока, где и что лежит. 90% понятно сразу, потому что очень дельно изложено. Знаю, что Python это инструмент к математике, на что явно указывают другие курсы Сергея. Вот потом от них и буду возвращаться к языку и досконально вникать в ньюансы. Еще раз спасибо!!!
Вторая часть видео не вызывает вопросов, но от первой немного закипает голова. Прошу прощения если мой вопрос глупый, я всего лишь учусь. Откуда вызывается метод __call__, если он не определен в классе? Я так понимаю из базового object. Но если мы его переопределим в нашем классе, как у вас показано, то вызывая класс для создания экземпляра, отработает __call__ из класса в котором __new__ нет и соответственно экземпляр не будет создан. Так же Вы говорили, что метод __new__ отработает всегда при создании экземпляра, тогда зачем его вызывать из __call__, как показано у вас в примере? Бывают глупые вопросы, ответить на которые сложно и долго, поэтому если об этом можно более подробно прочитать, подскажите где, буду признателен.
Да, у вас хороший вопрос. Здесь есть один нюанс. Когда мы определяем метод __call__, то он вызывается только для экземпляров класса, но не для самого класса. Поэтому, когда мы создаем объекты класса, например, pt = Point(), то здесь вызывается __call__ для класса, который определен в метаклассе type (о метаклассах я еще буду рассказывать). Надеюсь, теперь будет понятнее )
Вы очень доходчиво объясняете, но без практического примера, как использовать на практике такой метод, ничего не понятно. Т.е. в теории то оно пронятно, но где это тспользовать можно ?
Сергей, (традиционно) большое спасибо за урок! На 01:30 возник вопрос: как можно переопределить метод `__call__` для класса - и вообще, как программа различает методы `__call__` для класса и для объекта класса, если они выглядят одинаково? И сразу же заодно: я попробовала было отыскать метод `__call__` для класса через `cls.__dict__`, но его там не нашлось. Где он лежит в таком случае?
Спасибо! Все __call__ внутри классов - это для объектов. Если нужен __call__ для класса - это определяется в метаклассе (о них в конце плейлиста). Успехов!
Зддраствуйте Сергей Балакирев , Наверное вопрос странный но, когда мы вычисляли производную в методе КАЛЛ какое значение выбиралось для х если у него даже начального значения не было по сравнению с dx? И как работает __fn(x+dx) если __fn вычисляет синус на три
Как раз в принципе все функции в питоне - функторы по существу. Чистых функций и переменных в питоне как бы и нет🥴 все объекты, т.е. экземпляры классов
Нужно дополнительное пояснение, что то совсем запутался я. В момент создания экземпляра класса строкой df_sin = Derivate(df_sin) выполняется функция df_sin, так как аргумент func содержит ссылку на функцию df_sin и присваивает значение - sin(x), приватному атрибуту self.__fn, где x это аргумент принимающий значения = (х + dx) и (x) в строке формулы метода __Call__. Строка print(df_sin(math.pi/3) - запускает магический метод __Call__, где аргумент х получает значение - math.pi/3 и выполняется формула, результат которой, посредством команды return возвращается в функцию print, которая выводит результат на экран. Я все правильно понял?
Подскажите, если __call__ вызывается в момент создания экз класса, и он вызывает __new__ и __init__, то почему если делать пошагово то увидим , что сначала работает __new__ , затем __init__, и только если мы вызываем сам экземпляр то работает __call__
#12. Магический метод __call__. Функторы и классы-декораторы #dunder - методы от англ. double underscore #Магический метод __call__ ''' В действительности, когда происходит вызов класса, то автоматически запускается магический метод __call__ и в данном случае он создает новый экземпляр этого класса: ''' """ c = Counter() def __call__ (self, *args, **kwargs): obj = self._new_(self, *args, **kwargs) self._init_(obj, *args, **kwargs) return obj """ #Функторы - это классы с определённым оператором(). Мы сможем вызвать экз класса class Counter:
def __init__(self): print('вызов метода __init__') self.__counter = 0
def __new__(cls, *args, **kwargs): print('вызов метода __new__') return super().__new__(cls)
c = Counter() c2 = Counter() """Благодаря методу __call__, мы можем вызывать экземпляры класса подобно функции""" c() c(2) res = c(10) res2 = c2(-5) print(res, res2)
здесь метод __call__ вызывается у метакласса, а не тот, что объявлен в классе. Когда мы объявляем __call__ в классе, то он вызывается для объектов этого класса (не при создании, а при вызове их подобно функциям).
def __call__(self, mul, *args, **kwargs): def wrapper(x, dx=0.0001, *args, **kwargs): return (self.func(x + dx) - self.func(x)) / dx * mul return wrapper вопрос как в эту конструкцию поступает ссылка на функцию в пайчарме все сработало но если вспомнить функции декораторы, то там мы писали во внешней функции ссылку на функцию в качестве параметра здесь же я не понимаю где ссылка или она автоматически туда попадет при вызове __call__?
В методе call есть ссылка self, функция будет искаться в экземпляре класса, в котором определена функция (funk) через self.funk( ) - self тут основное.
Сергей здраствуйте! Скажите пожалуйста правильно ли я понял: сначала имя df_sin ссылается на объект функции в памяти и у этого объекта счетчик ссылок равен 1. Потом когда функция df_sin декорируется, имя df_sin ссылается на экземпляр класса Derivate. Получается счетчик ссылок уменьшается на 1 и мгновенно увеличивается на 1 за счет того, что атрибут __fn у экземпляра df_sin начинает ссылаться на эту область памяти.
Команда df_sin = Derivate(df_sin) создает объект класса Derivate и внутри объекта сохраняется ссылка на функцию df_sin. Далее, команда df_sin(math.pi/4) вызывает метод __call__ объекта класса Derivate и выполняется то, что записано внутри этого метода. Все, никаких счетчиков! Подробнее - телеграм-канал по Python.
Привет. Делал сайт по твоим видео, решил добавить функцию "Поделиться статьёй", но я потерпел неудачу. При отправке имейла, через send_mail() после "sock.connect(sa)", вылазит эта зараза "ConnectionRefusedError: [WinError 10061] Подключение не установлено, т.к. конечный компьютер отверг запрос на подключение".Весь интернет перерыл. Я могу тебе задонатить сколько скажешь(в пределал разумного).Буду благодарен невероятно!
Получается декораторы на классах менее гибки, потому что на них можно реализовать лишь двойной уровень вложенности. Чаще, как по мне, применяется тройной уровень вложенности. Да и для понимания тройного уровня вложенности не нужно знание ООП, только понимание областей видимости.
А зачем переопределять метод __call__, если мы можем просто не перезаписывать свойства? class DataBase: __instance = None def __new__(self, *args, **kwargs): if self.__instance is None: self.__instance = super().__new__(self) return self.__instance def __init__(self, user, psw, port): if not hasattr(self, 'user'): self.user = user if not hasattr(self, 'psw'): self.psw = psw if not hasattr(self, 'port'): self.port = port def __del__(self): self.__instance = None db1 = DataBase('root', '123456', 80) db2 = DataBase('root2', '456123', 40) print(id(db1), id(db2)) print(db1.__dict__) print(db2.__dict__)
не понимаю, зачем было усложнять пример синусами, пи, импортом math ??? очень отвлекает. Результат 0. и 16 цифр ...... нафиг он нужен? какая-то производная. куча слов которые сходу и не вспомнишь. функция должна быть x * 2 или х + 2!!!! вот и хватит. тут главное декораторы понять, а не вспомнить всю математику. p.s.: а на каком уроке объясняли что значит F7 и F8 ??? не понимаю, почему жмется то ф7, то ф8.
Согласен. Только это не урок английского. Я готов и к неидеальной дикции и к "русскому" английскому Сергея, т.к. для объяснения теории Питона это не существенно.
@@ValentinKurilyuk Ну, да. Поскольку видео про питон, строго запрещено потратить 10 минут и заглянуть в словарь. Видео посмотрят дети, они буду все это повторять. Оправдание - оно как ...
Грустно что в школах нет таких учителей, радостно что они есть на ютубе
Я думаю, если бы в школах платили такую же зарплату, что получают только очень хорошие программисты, то Сергей был бы там учителем. А свой собственный курс на степике, был бы неплохой добавкой к этой зарплате.
Сейчас профессию учителя просто втоптали в грязь. А ведь ее важность не меньше, чем у какого-нибудь врача. Врач жизни спасает. А чтобы стать хорошим врачом - надо выучиться. Хреновый учитель, даже будущего гения так отворожит от своего предмета, что тот до конца жизни будет считать себя бездарем в этой теме.
Супер)) Спасибо большое, Сергей) ещё бы обещанный Синглтон через __call__ и __new__ и будет счастье)
class MetaSingleton(type):
__instances = None
def __call__(cls, *args, **kwargs):
if cls.__instances is None:
cls.__instances = super().__call__(*args, **kwargs)
return cls.__instances
class Database(metaclass=MetaSingleton):
def __init__(self, user, psw, port):
self.user = user
self.psw = psw
self.port = port
db1 = Database('root', '123456', 80)
db2= Database('root2', '456123', 40)
print(id(db1), id(db2))
print(db1.__dict__)
print(db2.__dict__)
Так вот как реализуются классы декораторы - возился с этой тему,неделю,если не больше,и наконец то понял,спасибо тебе !
насколько ты красава просто передать не могу) молодец!😎
Выглядит намного красивее и компактнее, чем обычный вариант с вложенными функциями!
Особенно в случае с декоратором с параметрами, где 3 функции вложены друг в друга
Здорово! Получается намного компактнее, чем написать параметрический декоратор с кучей вложенных функций
Глубина курса уровня Бог) спасибо за погружение, уже почти нет рыбы, скоро увидим черных курильщиков)
Спасибо, посмотрела!
#43. Области видимости переменных. Ключевые слова global и nonlocal | Python для начинающих
ruclips.net/video/TacyWpUF1Kk/видео.html
#44. Замыкания в Python | Python для начинающих
ruclips.net/video/sJF7OMNgLUs/видео.html
#45. Введение в декораторы функций | Python для начинающих
ruclips.net/video/v0qZPplzwUQ/видео.html
#46. Декораторы с параметрами. Сохранение свойств декорируемых функций | Python для начинающих
ruclips.net/video/bl_CnIVpWmQ/видео.html
Тоже сразу вспомнились замыкания
Все понял, кроме вычисления самой производной)) Пожалуй, надо будет завтра обновить знание, что же это такое.
Божественно! Огромнейшая вам благодарность!!!!!!
Спасибо, товарищ Балакирев! лайк
Классы декораторы это круто!
Сергей,спасибо большое за урок,но заметил такую штуку,что в следующем уроке вы более понятно обьяснили
я посмотрел про str,repr,len,abs,а потом снова посмотрел этот урок и понял))
Лайк, но всё же присоединюсь к тем кого начало трясти от косинусов и синусов, нам бы на яблоках понять Сергей... ))
Потрясающе доходчиво
Офигеть как годно! Спасибище Сергей!!!
Спасибо за отличный урок 🫡
Я в перше зробив клас декоратор було інтересно!!! Дуже дякую👍
Спасибо. Ого! крутизна!
Спасибо за урок
Сергей, спасибо за объяснение! Вы для меня учитель №1 по Питону (его изучаю). Спасибо за все видео!
Супер)) Спасибо большое, Сергей) ещё бы обещанный Синглтон через _call_ и _new_ и будет счастье), самостоятельно я в тупике _ нужна помощь !!!! Тоже очень интересует этот вопрос
Самое ценное в этом уроке - вспомнил что такое производная). Немного отвлекся, освежил эту, благополучно забытую, математическую тему.
Еще бы уяснить разницу между производной функции и дифферениалом. По мне, сейчас, так это одно и то же.
Огромное спасибо Сергею Михайловичу! Изучаю Python пока в качестве хобби. Пробегаю по быстрому оба курса - начальный и ООП. Знакомлюсь пока, где и что лежит.
90% понятно сразу, потому что очень дельно изложено.
Знаю, что Python это инструмент к математике, на что явно указывают другие курсы Сергея. Вот потом от них и буду возвращаться к языку и досконально вникать в ньюансы.
Еще раз спасибо!!!
С Сергеем не только питон выучу , но и геометрию подтяну😄
Вот вам для сравнения подхода ООП и функционального.
Замыкание из урока, реализованное на функциях:
def strip_chars(chars):
def stripit(s):
res = s.strip(chars)
return res
return stripit
s1 = strip_chars(chars = '?:!.; ')
s2 = strip_chars(' ')
res = s1(' Hello world! ')
res2 = s2(' Hello world! ')
print(res)
print(res2)
Декоратор на функциях:
def derivate(func):
def wrapper(x, dx=0.0001):
res = (func(x + dx) - func(x)) / dx
return res
return wrapper
@derivate
def df_sin(x):
return math.sin(x)
#df_sin = derivate(df_sin)
print(df_sin(math.pi/3))
Вторая часть видео не вызывает вопросов, но от первой немного закипает голова. Прошу прощения если мой вопрос глупый, я всего лишь учусь.
Откуда вызывается метод __call__, если он не определен в классе? Я так понимаю из базового object. Но если мы его переопределим в нашем классе, как у вас показано, то вызывая класс для создания экземпляра, отработает __call__ из класса в котором __new__ нет и соответственно экземпляр не будет создан. Так же Вы говорили, что метод __new__ отработает всегда при создании экземпляра, тогда зачем его вызывать из __call__, как показано у вас в примере?
Бывают глупые вопросы, ответить на которые сложно и долго, поэтому если об этом можно более подробно прочитать, подскажите где, буду признателен.
Да, у вас хороший вопрос. Здесь есть один нюанс. Когда мы определяем метод __call__, то он вызывается только для экземпляров класса, но не для самого класса. Поэтому, когда мы создаем объекты класса, например, pt = Point(), то здесь вызывается __call__ для класса, который определен в метаклассе type (о метаклассах я еще буду рассказывать). Надеюсь, теперь будет понятнее )
@@selfedu_rus спасибо огромное, теперь все предельно понятно.
Спасибо!
Вы очень доходчиво объясняете, но без практического примера, как использовать на практике такой метод, ничего не понятно. Т.е. в теории то оно пронятно, но где это тспользовать можно ?
для этого курс на Stepik - ссылка под видео
От души!
Сергей, (традиционно) большое спасибо за урок! На 01:30 возник вопрос: как можно переопределить метод `__call__` для класса - и вообще, как программа различает методы `__call__` для класса и для объекта класса, если они выглядят одинаково? И сразу же заодно: я попробовала было отыскать метод `__call__` для класса через `cls.__dict__`, но его там не нашлось. Где он лежит в таком случае?
Спасибо! Все __call__ внутри классов - это для объектов. Если нужен __call__ для класса - это определяется в метаклассе (о них в конце плейлиста). Успехов!
Зддраствуйте Сергей Балакирев , Наверное вопрос странный но, когда мы вычисляли производную в методе КАЛЛ какое значение выбиралось для х если у него даже начального значения не было по сравнению с dx? И как работает __fn(x+dx) если __fn вычисляет синус на три
def __call__(self, x, dx=0.0001, *args, **kwargs)
второй параметр x - это значение аргумента (точки) в которой берется (вычисляется) производная
Подскажите пожалуйста, почему удаление символов (в 1 примере) происходит только в начале и в конце?
Может underscore?
разве это не тоже самое: ";hello world! ".strip("?:!,; ")? причем тут замыкание?
👍
Декораторы - это как китайский! Но очень интересно! :)))
Как раз в принципе все функции в питоне - функторы по существу. Чистых функций и переменных в питоне как бы и нет🥴 все объекты, т.е. экземпляры классов
Нужно дополнительное пояснение, что то совсем запутался я. В момент создания экземпляра класса строкой df_sin = Derivate(df_sin) выполняется функция df_sin, так как аргумент func содержит ссылку на функцию df_sin и присваивает значение - sin(x), приватному атрибуту self.__fn, где x это аргумент принимающий значения = (х + dx) и (x) в строке формулы метода __Call__. Строка print(df_sin(math.pi/3) - запускает магический метод __Call__, где аргумент х получает значение - math.pi/3 и выполняется формула, результат которой, посредством команды return возвращается в функцию print, которая выводит результат на экран. Я все правильно понял?
Про удаление символов не очень понятно. Повторила в точности программу - мне пишет "Аргумент должен быть строкой".
Вернувся ставити лайки великій людині)
👍👍👍👍👍
Что быстрее работает? Есть смысл использовать классы вместо декораторов?
Думаю, разницы в скорости вы здесь не заметите ) А так, что удобнее, то и используйте.
благодаря вам прохожу стажировку в Aston
У вас опечатка - "underscoRe" 😉
есть такое )
Крутий урок- розумієш як писати свої кастомні декоратори-класи
опечатка небольшая у вас, правильно не underscope, а underscore
да, заметил уже позже, спасибо! )
Подскажите, если __call__ вызывается в момент создания экз класса, и он вызывает __new__ и __init__, то почему если делать пошагово то увидим , что сначала работает __new__ , затем __init__, и только если мы вызываем сам экземпляр то работает __call__
#12. Магический метод __call__. Функторы и классы-декораторы
#dunder - методы от англ. double underscore
#Магический метод __call__
'''
В действительности, когда происходит вызов класса, то автоматически запускается
магический метод __call__ и в данном случае он создает новый экземпляр этого класса:
'''
"""
c = Counter()
def __call__ (self, *args, **kwargs):
obj = self._new_(self, *args, **kwargs)
self._init_(obj, *args, **kwargs)
return obj
"""
#Функторы - это классы с определённым оператором(). Мы сможем вызвать экз класса
class Counter:
def __init__(self):
print('вызов метода __init__')
self.__counter = 0
def __new__(cls, *args, **kwargs):
print('вызов метода __new__')
return super().__new__(cls)
def __call__(self, step = 1, *args, **kwargs):
print('вызов метода __call__')
self.__counter += step
return self.__counter
c = Counter()
c2 = Counter()
"""Благодаря методу __call__, мы можем вызывать экземпляры класса подобно функции"""
c()
c(2)
res = c(10)
res2 = c2(-5)
print(res, res2)
здесь метод __call__ вызывается у метакласса, а не тот, что объявлен в классе. Когда мы объявляем __call__ в классе, то он вызывается для объектов этого класса (не при создании, а при вызове их подобно функциям).
def __call__(self, mul, *args, **kwargs):
def wrapper(x, dx=0.0001, *args, **kwargs):
return (self.func(x + dx) - self.func(x)) / dx * mul
return wrapper
вопрос как в эту конструкцию поступает ссылка на функцию в пайчарме все сработало но если вспомнить функции декораторы, то там мы писали во внешней функции ссылку на функцию в качестве параметра здесь же я не понимаю где ссылка или она автоматически туда попадет при вызове __call__?
В методе call есть ссылка self, функция будет искаться в экземпляре класса, в котором определена функция (funk) через self.funk( ) - self тут основное.
Сергей здраствуйте! Скажите пожалуйста правильно ли я понял: сначала имя df_sin ссылается на объект функции в памяти и у этого объекта счетчик ссылок равен 1. Потом когда функция df_sin декорируется, имя df_sin ссылается на экземпляр класса Derivate. Получается счетчик ссылок уменьшается на 1 и мгновенно увеличивается на 1 за счет того, что атрибут __fn у экземпляра df_sin начинает ссылаться на эту область памяти.
Команда df_sin = Derivate(df_sin) создает объект класса Derivate и внутри объекта сохраняется ссылка на функцию df_sin. Далее, команда df_sin(math.pi/4) вызывает метод __call__ объекта класса Derivate и выполняется то, что записано внутри этого метода. Все, никаких счетчиков! Подробнее - телеграм-канал по Python.
Привет. Делал сайт по твоим видео, решил добавить функцию "Поделиться статьёй", но я потерпел неудачу. При отправке имейла, через send_mail() после "sock.connect(sa)", вылазит эта зараза "ConnectionRefusedError: [WinError 10061] Подключение не установлено, т.к. конечный компьютер отверг запрос на подключение".Весь интернет перерыл. Я могу тебе задонатить сколько скажешь(в пределал разумного).Буду благодарен невероятно!
Могу попробовать тебе помочь сам. Была такая ошибка у меня
@@mountaindeserver буду очень благодарен. Что от меня нужно?
Получается декораторы на классах менее гибки, потому что на них можно реализовать лишь двойной уровень вложенности. Чаще, как по мне, применяется тройной уровень вложенности. Да и для понимания тройного уровня вложенности не нужно знание ООП, только понимание областей видимости.
на уровне ООП вполне можно делать и декораторы с параметрами, если вы об этом (подробно рассматривается в курсе по ООП на Stepik)
А зачем переопределять метод __call__, если мы можем просто не перезаписывать свойства?
class DataBase:
__instance = None
def __new__(self, *args, **kwargs):
if self.__instance is None:
self.__instance = super().__new__(self)
return self.__instance
def __init__(self, user, psw, port):
if not hasattr(self, 'user'):
self.user = user
if not hasattr(self, 'psw'):
self.psw = psw
if not hasattr(self, 'port'):
self.port = port
def __del__(self):
self.__instance = None
db1 = DataBase('root', '123456', 80)
db2 = DataBase('root2', '456123', 40)
print(id(db1), id(db2))
print(db1.__dict__)
print(db2.__dict__)
Урок #12 = Пройден
Спасибо за урок. Пока что понятия не имею, где бы это могло пригодится, но все же, как говорится, лучше знать, чем не знать :)
11:00
не понимаю, зачем было усложнять пример синусами, пи, импортом math ??? очень отвлекает. Результат 0. и 16 цифр ...... нафиг он нужен? какая-то производная. куча слов которые сходу и не вспомнишь. функция должна быть x * 2 или х + 2!!!! вот и хватит. тут главное декораторы понять, а не вспомнить всю математику.
p.s.: а на каком уроке объясняли что значит F7 и F8 ??? не понимаю, почему жмется то ф7, то ф8.
тебе подробный гайд по блокноту тоже записать?
Можно бы попроще объяснять не включая сложные вычисления в код которые отвлекают от сути метода...
примеры нужно брать проще. 2+2 .А синусы косинусы тут ни чему. Потому что надо еще вспоминать что это такое.
Позор тебе, тут теорию гомотопий надо
Спасибо за видео!
Вот только.
Match читается "мэтч", а math - "мэз"!
Согласен. Только это не урок английского. Я готов и к неидеальной дикции и к "русскому" английскому Сергея, т.к. для объяснения теории Питона это не существенно.
@@ValentinKurilyuk
Ну, да.
Поскольку видео про питон, строго запрещено потратить 10 минут и заглянуть в словарь.
Видео посмотрят дети, они буду все это повторять.
Оправдание - оно как ...
"матч"... Хд
math - мэвс