Урок #9 = Пройден Этот урок полностью поменял мой взгляд на сеттеры и геттеры. Это просто имхо. Даже не мог подозревать, что все настолько может быть упрощенным. P.S. Я уже чуток потренировался, и как же я был в шоке от того, как же это удобно. Буду теперь на постоянной основе его использовать. Спасибо Вам, Сергей. Жму руку🤝 И ведь это только 9-й урок (10 видео)...я в предкушении, что будет в следующих 30 уроках)
Методы property возвращают объект property, поэтому следующий код одинаковый: old = property(get_old, set_old) равен old = property() old = old.getter(get_old) old = old.setter(set_old) равен old = property().getter(get_old).setter(set_old)
Спасибо. Про декораторы знал, но то что это методы класса property - это нигде не разу не встречал. Было интересно посмотреть как это работает изнутри.
Много где облазил, но объяснения от автора, имхо, лучшее что есть на ютюбе на русском языке. Если бы был поллноценный курс на степике или типа того, обязательно заплатил бы! Спасибо!
Скорее всего вопрос, который я задам, опытным коллегам покажется максимально глупым, однако мой жизненный опыт говорит о том, что лучше показаться глупым в обучении, чем оказаться глупым в "бою". Посему вопрос: для чего сначала запрещать доступ к атрибутам извне посредством присвоения им статуса private, а потом достаточно хитрым методом реализовать через декоратор в классе возможность обеспечить доступ к этим же самым атрибутам опять-таки извне? Если не сложно, не могли бы описать какой-нибудь пример из реальной практики, когда это необходимо? Заранее большое спасибо за ответ и огромное уважение и благодарность автору за этот замечательный курс!
Спасибо! Классический вопрос. Пусть есть класс Window - окно на экране. У него есть два свойства height и width (высота и ширина), мы создаем объект w = Window(), а затем, меняем высоту w.height = 200. Что должно произойти при этом действии? Во-первых, измениться соответствующее свойство (с проверкой корректности данных) и, во-вторых, измениться в размерах само окно на экране. Сделать это через обычную переменную с доступом извне не получится.
Дмитрий! Я, как и Вы - учусь и точно также оочень длительное время задавался именно этим вопросом... пока не понял его полностью! Если Вас не устроил ответ Учителя - могу Вам предложить обьяснение от себя-Чайника... ) может Вам легче будет понять - как художник - художника...)
@@maksshcherbakov8533 Макс! Мне лично хорошо запоминаются жизненные примеры. Допустим мы с Вами пишем комплекс для проектирования мебели. Запоминаем: для производства мебели нам поставляют плиты размером 2 х 3 м и допустим - одинаковой толщины - 20 мм. Вы - пишете модуль для подсчета расхода материала (наших мебельных плит). Вы создаете класс Plate (плиты) c локальными свойствами x, y, z (ширина, высота, толщина). Каждый раз - когда я создаю экземпляр Вашего класса (это значит - я отрезал кусок плиты) - Вы делаете расход материала. А теперь Главное: если свойства x, y, z будут public - я могу создавать экземпляры (отрезать куски) размером больше допустимого... и даже по ошибке - могу заказать кусок (попробовать создать экземпляр) a = Plate(1, "Hello", 30). Сделав все три параметра x, y, z - приватными - Вы можете перед каждым созданием экземпляра класса проверять в сеттере - на правильность типа (например только int), на соответствие допустимому диапазону (например - ширина до 3 м), можете запретить изменение параметра z - толщине (все плиты по договоренности - одинаковой толщины 20 мм). С одной стороны - у нас инкапсуляция - с другой стороны - модуль же должен иметь связь с внешним миром! Вот мое лично субьективное понимание сути вопроса. Попробуйте найти некоторые подтверждения моих мыслей в базовом (начальном) уроке по сеттерам и геттерам.
Хороший и полезный ролик 😌 как дойду до наследования дам свой полный фидбэк на обновленный курс по ооп😌 но в любом случае сразу благодарю автора!!!!видно что работа огромная проделана
У меня появились 2 вопроса: на 8:30 вы говорите, что приоритет у объекта свойства property old выше, чем у создаваемой пары ключ-значение в словаре объекта класса Person. Однако, если мы создаем не пару p.__dict__['old'] = 'some string...', а пару p.__dict__['_Person__old'] = 'some string...', то значение ключа _Person__name в словаре отлично меняется с 35 на 'some string'. Вопросы: 1) Получается, дело не в приоритетности объекта свойства property, а в том, что мы изначально создавали в словаре и потом работали при помощи old = property (...) с атрибутами типа _Person__name и _Person__old (что соответствует self.__name и self.__old), а теперь пытаемся поменять self.__old в словаре на self.old , что выдает 2 разных ключа, что логично, так как мы работаем с разными аттрибутами. 2) Существует ли действительная приоритетность объектов свойства property перед простым заданием пары значений в словаре ({ключ: значение}) или объекты свойства property лучше использовать только для того, чтобы работать с вереницами сеттеров - геттеров - дилитеров? Поправьте, если неправ. И огромное спасибо за уроки!!!
Здравствуйте! Конечно, когда вы обращаетесь по имени _Person__old, то это имя отличается от имени атрибута-свойства old, поэтому приоритеты здесь не включаются. Попробуйте то же самое с обычным атрибутом old. Здесь будет идти обращением именно к свойству (property), а не переменной. А вообще на такие вопросы вам с радостью ответят в сообществе ТГ-канала по Python (ссылка под видео).
Не пойму чем простые геттеры и сеттеры 02:30 уступает этому 04:42 (property(get_old, set_old)) и уж нем более чем 13:26 (@property + @get_old). Последнее ну ни разу не выглядит проще и интуитивнее. Или я что-то не понимаю?
Вначале ролика сказали, что трудно следить за прописыванием каждому атрибуту методов геттер и сеттер. И в итоге прописали аналогично и свойство для атрибута и свойство.сеттер. Мысль чем это лучше\удобней в итоге не ясна, только тем что имя одно? По итогу так же для каждого атрибута прописывать свойство нужно, и чем это лучше?
Может кто-то объяснить? Когда у нас в классе 3 переменных олд, почему не нарушается логика? Ведь обычно в таких случаях переменная просто меняет значение. 12:51
Дорого времени суток, видео 🔥. Но есть вопрос: если сделать не __age, a age, то выходит ошибка, связанная с рекурсией. Можете пожалуйста объяснить почему?
Я правильно понимаю, что это нужно для того, что бы если мы заранее не знаем имя нового атрибута мы таким образом защищаем от изменений важные для работы класса атрибуты? Ну т.е. если пользователь в последствии создаст экземпляр класса, добавит в него атрибут old, то это никак не повлияет на атрибут самого класса. Таким образом у нас не пересекаются имена атрибутов и при желании можно изменить атрибут old самого класса, а не его экземпляра?
Немного не понял вот этого: old = property() old = old.setter(set_old) old = old.getter(get_old) Разве мы каждой строчкой не переопределяем атрибут old?
Тоже обратил на это внимание. Мой уровень знаний пока не позволяет понять как работает данный объект. Что происходит при вызове экземпляр класса old? Как он сам определяет какой метод вызвать...
Отличное видео! Но остались вопросы. Ваш пример с Window (приведённый под другим комментарием). Нельзя ли вместо property использовать магический метод __set_attr__, в котором мы будем проверять, какое свойство мы изменяем, и если это width или height, то, соответственно, делаем то что надо. Заранее спасибо)
Рекомендую тем кто в замешательстве, как был я паралельно клацать в пайчарме и пробовать, а то столько всего в ООП что уже теряешь себя в пространстве)
Добрый день! Спасибо за вашу работу. Прошу ответить на пару вопросов, если Вас не затруднит. 1) Подскажите, декоратор @property обязательно только перед геттером стоит ( 14:25 )? И почему именно перед ним? Исторически сложилось? 2) В каком случае возможно использование декоратора @old.getter ? Заранее благодарю!
Возможно, это восходит к дескрипторам (данных и не данных), где метод get() строго обязателен. А, вообще, следует воспринимать как элемент языка и просто запомнить. Этот декоратор можно использовать для переопределения геттера.
Спасибо ! В отличии от урока в предыдущем курсе по ООП этот действительно более понятен, посмотрел с удовольствием! ) Однако хочется прояснить один момент: В классе когда мы делаем свойства через декораторы... old = property() old = old.getter(fun) old = old.setter(fun2) Правильно ли я понимаю, что здесь происходит как бы 'напихивание декорированных методов в переменную - old' т. е это не нужно воспринимать как обычное присваивание. Имею в виду, что если бы имя - 'old' не было объектом property то такое присваивание каждый раз связывало бы с этим именем новый метод. Какой-то протокол под капотом ?
Все равно не понятно: У себя в пайчарме 2 класса создал, один как у вас в примере, с приватными свойствами, которые становятся доступными через геттер и сеттер, и у которых мы меняем названия с помощью property чтобы было проще обращаться. Второй класс, который использует просто публичные атрибуты self.name и self.old. Вот теперь вопрос - а какая разница? Получается в первом примере мы сначала по сути сделали их приватными, а потом обратно с помощью нехилых таких костылей сделали публичными. В первом примере 13 строк кода, и по сути все атрибуты - публичные, потому что их можно поменять обратившись таким образом - p.old = 30 (просто тут old ссылается на сеттер, которому разрешено поменять приватный атрибут self.__old). Во втором примере я просто прописал публичный атрибут self.old и по сути меняю его такой же строкой кода - p.old = 30. Но тут всего 4 строки кода. Я понял задумку с приватными атрибутами и сеттерами , геттерами (хотя тут тоже логика, да? - делать недоступными, чтобы потом опять сделать доступными. Но тут хоть одну причину вижу - чтобы явно их не менять), но логику с property не пойму все равно. Тут же все тоже самое что и с обычными публичными атрибутами в плане написания кода. В первом примере чтобы узнать old я напишу - print(p.old) И во втором примере я напишу то же самое - print(p.old). Тогда зачем все это? (Ниже разъяснения я прочитал, но там все равно не понятно)
Так, теперь вопрос на засыпку. Зачем все это делать в данном примере, если мы можем в теле класса написать self.old вместо self.__old. По сути, к этому же и пришли?
извне не можем, только внутри (хотя извне тоже можно исхитриться, но это уже будет на совести программиста); приватные переменные - это не защита от хакеров, это пометка для программиста, что использовать только внутри класса
@@selfedu_rus пересмотрел и понял. Если бы мы не задавали сеттер через property, то у нас создавалась бы новая переменная в самом объекте, а не изменялся бы атрибут класса. Пропустил момент про приоритет property. Спасибо за уроки!
Добрый день! Подскажите пожалуйста, почему вот такая ошибка. Если один аргумент в сеттере то все ок, если два то такая ошибка.. Traceback (most recent call last): File "/Users/maxvolkoff/PyPro/teach_n0/classes_4.py", line 18, in pt.min_max = (1, 2) TypeError: Class.min_max() missing 1 required positional argument: 'max'
А вообще - странная конструкция получается. Приватные атрибуты подразумевают отсутствие доступа к ним извне. Но мы делаем "property", в результате чего получаем доступ к приватным атрибутам извне. Т.е. делам приватный атрибут публичным.
зато теперь можно наложить логику изменения или чтения приватного значения. В публичном можно было бы поменять на любое значение, а тут теперь можем наложить какое-нибудь условие
Ну во-первых, ту же логику расширить на protected аргументы. Во-вторых в этой же логике вы можете докрутить дополнительные проверки, эксепшны и так далее
Почему когда мы обращаемся к сеттеру, через оператор присваивания = происходит вызов функции. У меня одно объяснение он переопределен в классе property и выполняет другое действие как скобочки (). По аналогии с переопределением __add__, когда + будет делать заданный функционал а не сложение/конкатенацию. Я прав?
пока только пришло в голову в геттер или сеттер добавить проверку пароля, например добавить инпут введите кодовое слово и если есть совпадение, то можно извлечь или переопределить свойство...
Получается, к методам с одинаковым именем применяются разные декораторы, которые делают из метода объект property. Интерпретатор понимает какой метод исполнять, в зависимости какой оператор был использован: оператор присвоения - setter, оператор del - deleter, без оператора - getter?
@@zakirovio вероятно тут все завязано на сигнатуры. Вы можете без всяких классов написать кучу просто функций с одинаковым именем но разными аргументами на вход - интерпретатор посчитает их как разные функции и будет выбирать исходя из ситуации нужную. Рызные декораторы над объявленной функцией так же меняют сигнатуру, получается похожая логика
@@lemonade0224при определении множества функций с одинаковыми именами, вызываться будет только последняя, ее область видимости будет перекрывать другие
объект класса property скорее всего имеет доступ к ссылкам этих одноименных методов и при использовании определенного оператора или инструкции применяет setter. getter или deleter
Сергей, можно ли через property setter изменять два атрибута одновременно, например имеем две стороны прямоугольника А и В. В примере у Вас нужно делать свойство на каждый атрибут, а чисто логично бы сделать одной свойство к на обе стороны прямоугольника... Спасибо заранее.
День добрый, уважаемый Сергей есть вопрос. А property в 5 подвиге нам пришлось как бы дублировать отдельно для width и height тоесть получилось для одного сетер и гетер и для другого сетер и геттер а нельза было для двух обьектов-свойств записать один геттер и сеттер или для каждого объекта свойства должен быть отдельный геттер и сеттер?
Спасибо за видео, все очень понятно, но есть вопрос: можно ли таким образом в сеттер передать два значения? Допустим у на с класс Poіnt, у точки две координаты, можно через @property задават два значения?
Спасибо! Я два года с ним знаком. Но здесь важен еще прежний опыт программирования, те кто уже знает другие языки быстрее изучают новые, т.к. много похожего ))
не очень все-таки понятно зачем нужен этот декоратор. Получается, что с помощью него осуществляется доступ к защищенным свойствам. Но можно просто убрать двойное нижнее подчеркивание впереди и получится тот же эффект, без нагромождения сеттеров и геттеров. Разве что в самих этих функциях можно вставлять дополнительные условия проверки на присвоение определенных значений.
Здесь нет никакого присваивания, всего лишь применяется декоратор setter к функции set_get и декоратор getter к функции get_old, чтобы обеспечить работу свойства old
Добрый день. Вопрос, касающийся свойства property. Правильно ли я понимаю, что имеет значение порядок методов, указанных в свойстве property: на первом месте всегда метод, обеспечивающий получение значения атрибута, на втором - метод для задания значения атрибута, на третьем - метод для удаления значения атрибута, на четвертом - строка, содержащая документацию? property(getx, setx, delx, "I am the property.") И при изменении значения атрибута интерпретатор понимает, что необходимо вызвать метод, указанный на второй позиции свойства property, при зачитывании значения атрибута - метод, указанный на первой позиции свойства property и т.д. ?
доброе время суток, у меня вопрос: какой смысл делать переменную age закрытой, если мы по факту делаем с ней абсолютно тоже самое благодаря геттерам и сеттерам и вне кода класса работа с атрибутами никаким образом не меняется. Грубо говоря код из конца видео == тому чтобы переменную не делать закрытой
Идея в том, что теперь есть _возможность_ добавить нужный функционал во время записи/чтения атрибута, при этом пользователи класса (другие объекты/классы которые работают с нашим классом) не должны знать об этом, им это неважно. Они просто работают со свойствами, а мы, как создатели нашего класса можем эти свойства проверять, применять, обрабатывать любым нужным способом. Без гетера/сетера т.е. без этой дополнительной прослойки никакой возможности проверить что пишется в проперти и что оттуда достается - нет. Пример в видео несколько искусственный (потому что нет реальной задачи и в гетера и сетерах действительно ничего не делается) но при этом полностью достаточный для того чтобы показать как работает этот механизм в питоне. Это пример инкапсуляции.
@@osman3d я уже понял это на момент написания вашего комментария, просто сам недавно до классов дошел и на каждом из встреченных мною гайдов с ютуба толком тема закрытых переменных не растолкована. Спасибо за ответ в любом случае и знайте что вы абсолютно правы, на момент написания комментария я в классах не понимал ровным счетом ничего
"Если в классе задан атрибут как объект-свойство, то в первую очередь выбирается оно...", a как тогда обратиться к локальному атрибуту с таким же именем?
Здравствуйте, много где облазил - ничего не нашел. Надеюсь вы ответите.Почему мы не можем просто сразу создать метод private, почему нужно создавать публичный, а потом в нем делать return private. Вот допустим: @property def lvl(self): return self.__lvl, f'{dt.now() - self.__born}' @lvl.setter def lvl(self,numer): self.__lvl += numer Почему нельзя сразу создать def __lvl(self)? Заранее спасибо!
приватные атрибуты - это служебные (как правило, переменные) внутри класса и менять их извне не предполагается. Но если все же нужно получать или менять их значения, то прописывают сеттеры/геттеры или объекты-свойства, где выполняют дополнительную проверку на правильность передачи значений. Подробнее вам могут ответить в телеграм-канале по Python.
Сергей, подскажите, если использовать property и не использовать атрибуты типа _ _private , то возникает ошибка так как у нас не будет присутствовать свойство , которое мы сделали с помощью property. К примеру у меня будет отсутствовать свойство health class Player: def __new__(cls, *args, **kwargs): print(f'Вызов метода __new__') return object.__new__(cls) def __init__(self,name, health, lvl): self.name = name self.health = health self.lvl = lvl @property def health(self): return self.health @health.setter def health(self, value): if value in (int,float): self.health = value # else: # raise TypeError('Здоровье должно быть написано цифрами') # p1= Player('Henry', 100, 5) print(p1.__dict__) print(p1.health) ---- > ОШИБКА
Посмотрел 4 минуты и не понимаю, в чём практический/сакральный/иной смысл этих манипуляций? Сначала мы сделали атрибуты приватными, затем расприватили их, чтобы иметь возможность обращаться к ним. Для чего? print(class_name.__dict__) показывает все наши "приватные" данные Единственное, что удобно = old = property(get_old, set_old), как дальнейшее использование чтения/записи используя прдемонстрированный в видео подход. Но стоит ли оно того, чтобы каждый раз это прописывать?
Касаемо функционального дублирования. Почему бы вместо докорирования геттеров и сеттеров не сделать сами геттеры и сеттеры приватными, и передавать в объект property приватные геттеры и сеттеры?
Вот эта конструкция не ясна old = property() old = old.setter(set_old) old = old.getter(get_old) Больно уж похоже на оверрайд одного и того же атрибута разными объектами
все равно не понимаю, зачем мы запрещаем программисту обращаться к свойствам объекта напрямую: p.old а потом городим еще кучу строчек, чтобы он все-таки потом мог обращаться к свойствам объекта визуально и по сути будто напрямую: p.old Почему бы нам сразу не разрешить ему иметь доступ к свойству напрямую?
В чем смысл такого функционала? Приватизировать, потом создавать декораторы, чтоб обращаться к методам класса, в чем смысл можете объяснить, чтоб я понимал в чем была цель такой логики в классах?
одно через другое через третье, фиг знает что., А где бл... постулаты пайтона - явное лучше неявного, Простое - лучше сложного. вопрос - нахера тьак все усложнять , мало вижу пользы в этом все по итогу Только голову ломать
Я бы назвал поле old не свойство класса , а лямбда функция , которая работает двояко , в зависимости от чтения или записи. Просто очень похоже на поведение лямбда функции 🤔
у Вас талант к преподаванию, весь материал излагаете последовательно и доходчиво
Если кому-то сложно освоить материал, что-то не получается, то лучше отдохнуть и вернуться к этому уроку через время
Это должно помочь
Урок #9 = Пройден
Этот урок полностью поменял мой взгляд на сеттеры и геттеры. Это просто имхо. Даже не мог подозревать, что все настолько может быть упрощенным.
P.S. Я уже чуток потренировался, и как же я был в шоке от того, как же это удобно. Буду теперь на постоянной основе его использовать. Спасибо Вам, Сергей. Жму руку🤝
И ведь это только 9-й урок (10 видео)...я в предкушении, что будет в следующих 30 уроках)
Сергей, спасибо за ваши видео!!!
Просто супер!!!
Самое комплексное и понятное объяснение!!!
Все ваши видео смотрю!!!
Наконец-то нормально объяснили как это все работает. Спасибо!
Как же шикарно все объяснено, просто по полочкам. Респект!!!
Методы property возвращают объект property, поэтому следующий код одинаковый:
old = property(get_old, set_old)
равен
old = property()
old = old.getter(get_old)
old = old.setter(set_old)
равен
old = property().getter(get_old).setter(set_old)
Невероятно простая подача сложного материала все понятно! Спасибо!
Спасибо. Про декораторы знал, но то что это методы класса property - это нигде не разу не встречал. Было интересно посмотреть как это работает изнутри.
Много где облазил, но объяснения от автора, имхо, лучшее что есть на ютюбе на русском языке. Если бы был поллноценный курс на степике или типа того, обязательно заплатил бы! Спасибо!
Сергей, мы вас рассекретили, разлогиньтесь)
@@leshen_show не, а что? бизнес, ничего личного! А так Сергею огромное спасибо за курс))
Є ще egoroff_channel
ты просто гениально все объясняешь ! спасибище!!!
2.5 недели назад не понял, что такое декораторы в итоге прошел весь ваш курс на степике по питону. Вернулся и теперь все стало ясно.
ссылку на курс можно?)
Скорее всего вопрос, который я задам, опытным коллегам покажется максимально глупым, однако мой жизненный опыт говорит о том, что лучше показаться глупым в обучении, чем оказаться глупым в "бою".
Посему вопрос: для чего сначала запрещать доступ к атрибутам извне посредством присвоения им статуса private, а потом достаточно хитрым методом реализовать через декоратор в классе возможность обеспечить доступ к этим же самым атрибутам опять-таки извне? Если не сложно, не могли бы описать какой-нибудь пример из реальной практики, когда это необходимо?
Заранее большое спасибо за ответ и огромное уважение и благодарность автору за этот замечательный курс!
Спасибо! Классический вопрос. Пусть есть класс Window - окно на экране. У него есть два свойства height и width (высота и ширина), мы создаем объект w = Window(), а затем, меняем высоту w.height = 200. Что должно произойти при этом действии? Во-первых, измениться соответствующее свойство (с проверкой корректности данных) и, во-вторых, измениться в размерах само окно на экране. Сделать это через обычную переменную с доступом извне не получится.
Дмитрий! Я, как и Вы - учусь и точно также оочень длительное время задавался именно этим вопросом... пока не понял его полностью! Если Вас не устроил ответ Учителя - могу Вам предложить обьяснение от себя-Чайника... ) может Вам легче будет понять - как художник - художника...)
Я думаю что можно впихнуть какие то проверки или действия перед передачей или записью
@@andrewharazdowskyy4771 я не Дмитрий, но был бы рад еще одному объяснению
@@maksshcherbakov8533 Макс! Мне лично хорошо запоминаются жизненные примеры. Допустим мы с Вами пишем комплекс для проектирования мебели. Запоминаем: для производства мебели нам поставляют плиты размером 2 х 3 м и допустим - одинаковой толщины - 20 мм. Вы - пишете модуль для подсчета расхода материала (наших мебельных плит). Вы создаете класс Plate (плиты) c локальными свойствами x, y, z (ширина, высота, толщина). Каждый раз - когда я создаю экземпляр Вашего класса (это значит - я отрезал кусок плиты) - Вы делаете расход материала. А теперь Главное: если свойства x, y, z будут public - я могу создавать экземпляры (отрезать куски) размером больше допустимого... и даже по ошибке - могу заказать кусок (попробовать создать экземпляр) a = Plate(1, "Hello", 30). Сделав все три параметра x, y, z - приватными - Вы можете перед каждым созданием экземпляра класса проверять в сеттере - на правильность типа (например только int), на соответствие допустимому диапазону (например - ширина до 3 м), можете запретить изменение параметра z - толщине (все плиты по договоренности - одинаковой толщины 20 мм). С одной стороны - у нас инкапсуляция - с другой стороны - модуль же должен иметь связь с внешним миром! Вот мое лично субьективное понимание сути вопроса. Попробуйте найти некоторые подтверждения моих мыслей в базовом (начальном) уроке по сеттерам и геттерам.
Спасибо! Очень понятно объясняете, сразу всё ясно
второй раз вы лучше это обьяснили, чем в первом плейлисте)))
Хороший и полезный ролик 😌 как дойду до наследования дам свой полный фидбэк на обновленный курс по ооп😌 но в любом случае сразу благодарю автора!!!!видно что работа огромная проделана
Спасибо, посмотрела!
Автор, желаю тебе миллион подписчиков за втой труд!
Cпасибо за отличный курс. Если есть ещё здесь старички как я, то за шестёрёнкой на видео можно понизить скорость до 0.75, как я делаю ;)
Декоратор очень полезный, сокращает количество кода. Уже испробовал в модели Django проекта.
спасибо за Вашу работу.
Проще гораздо работать напрямую через set и get, плюс добавив docstring
Реализация через property существенно усложняет сопровождение кода
Потрясающе!
У меня появились 2 вопроса: на 8:30 вы говорите, что приоритет у объекта свойства property old выше, чем у создаваемой пары ключ-значение в словаре объекта класса Person. Однако, если мы создаем не пару p.__dict__['old'] = 'some string...', а пару p.__dict__['_Person__old'] = 'some string...', то значение ключа _Person__name в словаре отлично меняется с 35 на 'some string'.
Вопросы: 1) Получается, дело не в приоритетности объекта свойства property, а в том, что мы изначально создавали в словаре и потом работали при помощи old = property (...) с атрибутами типа _Person__name и _Person__old (что соответствует self.__name и self.__old), а теперь пытаемся поменять self.__old в словаре на self.old , что выдает 2 разных ключа, что логично, так как мы работаем с разными аттрибутами.
2) Существует ли действительная приоритетность объектов свойства property перед простым заданием пары значений в словаре ({ключ: значение}) или объекты свойства property лучше использовать только для того, чтобы работать с вереницами сеттеров - геттеров - дилитеров?
Поправьте, если неправ. И огромное спасибо за уроки!!!
Здравствуйте! Конечно, когда вы обращаетесь по имени _Person__old, то это имя отличается от имени атрибута-свойства old, поэтому приоритеты здесь не включаются. Попробуйте то же самое с обычным атрибутом old. Здесь будет идти обращением именно к свойству (property), а не переменной.
А вообще на такие вопросы вам с радостью ответят в сообществе ТГ-канала по Python (ссылка под видео).
Стільки інфи в 16 хв. Сергей в ударі!
спасибо тебе огромное, дорогой!
👍👍👍👍
спасибо за урок
Не пойму чем простые геттеры и сеттеры 02:30 уступает этому 04:42 (property(get_old, set_old)) и уж нем более чем 13:26 (@property + @get_old).
Последнее ну ни разу не выглядит проще и интуитивнее.
Или я что-то не понимаю?
Сергей, благодарю!! 👍🔥
Нормально! На других каналах, где повествуется эта тема, вообще ничего не понять.
Отлично, спасибо
Вначале ролика сказали, что трудно следить за прописыванием каждому атрибуту методов геттер и сеттер. И в итоге прописали аналогично и свойство для атрибута и свойство.сеттер. Мысль чем это лучше\удобней в итоге не ясна, только тем что имя одно? По итогу так же для каждого атрибута прописывать свойство нужно, и чем это лучше?
пользоваться потом проще, обращаеимся по одному имени и для записи и для чтения в этом удобство
Спасибо! Очень полезное видео!
Очередной раз нашёл много того, чего не знал, спасибо!
Пошла жара ))
Пора изменить название канала на Супер препод!
Спасибо!
У меня пиявились знания )
Может кто-то объяснить? Когда у нас в классе 3 переменных олд, почему не нарушается логика? Ведь обычно в таких случаях переменная просто меняет значение. 12:51
Спасибо за уроки 🖖👍
Спасибо. Понятно. Странно только - пользуемся вроде абстракцией в виде класса, но лезем ей в кишки (совсем не абстрактно).
спасибо!
класс
все супер, доступно и понятно. спасибо. но почему не Age, а Old?))
how old are you
Дорого времени суток, видео 🔥. Но есть вопрос: если сделать не __age, a age, то выходит ошибка, связанная с рекурсией. Можете пожалуйста объяснить почему?
такой же вопрос, если не ошибаюсь в предыдущих роликах автор обговаривал эту ошибку, но не помню где именно
Я правильно понимаю, что это нужно для того, что бы если мы заранее не знаем имя нового атрибута мы таким образом защищаем от изменений важные для работы класса атрибуты? Ну т.е. если пользователь в последствии создаст экземпляр класса, добавит в него атрибут old, то это никак не повлияет на атрибут самого класса. Таким образом у нас не пересекаются имена атрибутов и при желании можно изменить атрибут old самого класса, а не его экземпляра?
Можно вопрос? сколько вам сейчас лет?
Немного не понял вот этого:
old = property()
old = old.setter(set_old)
old = old.getter(get_old)
Разве мы каждой строчкой не переопределяем атрибут old?
Тоже обратил на это внимание. Мой уровень знаний пока не позволяет понять как работает данный объект. Что происходит при вызове экземпляр класса old? Как он сам определяет какой метод вызвать...
Отличное видео! Но остались вопросы. Ваш пример с Window (приведённый под другим комментарием). Нельзя ли вместо property использовать магический метод __set_attr__, в котором мы будем проверять, какое свойство мы изменяем, и если это width или height, то, соответственно, делаем то что надо. Заранее спасибо)
Можно, но property позволяет разнести код по отдельным методам, что с точки зрения красоты куда лучше.
Спасибо, буду знать
Рекомендую тем кто в замешательстве, как был я паралельно клацать в пайчарме и пробовать, а то столько всего в ООП что уже теряешь себя в пространстве)
Добрый день!
Спасибо за вашу работу. Прошу ответить на пару вопросов, если Вас не затруднит.
1) Подскажите, декоратор @property обязательно только перед геттером стоит ( 14:25 )? И почему именно перед ним? Исторически сложилось?
2) В каком случае возможно использование декоратора @old.getter ?
Заранее благодарю!
Возможно, это восходит к дескрипторам (данных и не данных), где метод get() строго обязателен. А, вообще, следует воспринимать как элемент языка и просто запомнить.
Этот декоратор можно использовать для переопределения геттера.
@@selfedu_rus но даже при переопределении геттера, декоратор property будет у "старого" геттера?
@@v_alik Вот, переопределется:
class Person:
def __init__(self, name, old):
self.__name = name
self.__old = old
@property
def get_old(self):
return self.__old
@get_old.setter
def get_old(self, old):
self.__old = old
@get_old.getter
def get_old(self):
return self.__old + 10
@@selfedu_rus Тогда
@property
def get_old(self):
return self.__old
перестает быть геттером? и тогда зачем он остался, почему бы не стереть?
Сергей, не совсем понял на 7:37 речь же идет о локальных атрибутах, а не о локальных свойствах или не так?
это одно и то же
с 3 - го раза понял и освоил тему ахах
Спасибо ! В отличии от урока в предыдущем курсе по ООП этот действительно более понятен, посмотрел с удовольствием! )
Однако хочется прояснить один момент:
В классе когда мы делаем свойства через декораторы...
old = property()
old = old.getter(fun)
old = old.setter(fun2)
Правильно ли я понимаю, что здесь происходит как бы 'напихивание декорированных методов в переменную - old' т. е это не нужно воспринимать как обычное присваивание.
Имею в виду, что если бы имя - 'old' не было объектом property то такое присваивание каждый раз связывало бы с этим именем новый метод.
Какой-то протокол под капотом ?
Да, все верно, old - это общий декоратор, в котором будет два метода для setter и getter
@@selfedu_rus спасибо.
Все равно не понятно:
У себя в пайчарме 2 класса создал, один как у вас в примере, с приватными свойствами, которые становятся доступными через геттер и сеттер, и у которых мы меняем названия с помощью property чтобы было проще обращаться.
Второй класс, который использует просто публичные атрибуты self.name и self.old.
Вот теперь вопрос - а какая разница?
Получается в первом примере мы сначала по сути сделали их приватными, а потом обратно с помощью нехилых таких костылей сделали публичными. В первом примере 13 строк кода, и по сути все атрибуты - публичные, потому что их можно поменять обратившись таким образом - p.old = 30 (просто тут old ссылается на сеттер, которому разрешено поменять приватный атрибут self.__old).
Во втором примере я просто прописал публичный атрибут self.old и по сути меняю его такой же строкой кода - p.old = 30. Но тут всего 4 строки кода.
Я понял задумку с приватными атрибутами и сеттерами , геттерами (хотя тут тоже логика, да? - делать недоступными, чтобы потом опять сделать доступными. Но тут хоть одну причину вижу - чтобы явно их не менять), но логику с property не пойму все равно. Тут же все тоже самое что и с обычными публичными атрибутами в плане написания кода. В первом примере чтобы узнать old я напишу - print(p.old) И во втором примере я напишу то же самое - print(p.old). Тогда зачем все это?
(Ниже разъяснения я прочитал, но там все равно не понятно)
Так, теперь вопрос на засыпку. Зачем все это делать в данном примере, если мы можем в теле класса написать self.old вместо self.__old. По сути, к этому же и пришли?
извне не можем, только внутри (хотя извне тоже можно исхитриться, но это уже будет на совести программиста); приватные переменные - это не защита от хакеров, это пометка для программиста, что использовать только внутри класса
@@selfedu_rus пересмотрел и понял. Если бы мы не задавали сеттер через property, то у нас создавалась бы новая переменная в самом объекте, а не изменялся бы атрибут класса. Пропустил момент про приоритет property. Спасибо за уроки!
Добрый день! Подскажите пожалуйста, почему вот такая ошибка.
Если один аргумент в сеттере то все ок, если два то такая ошибка..
Traceback (most recent call last):
File "/Users/maxvolkoff/PyPro/teach_n0/classes_4.py", line 18, in
pt.min_max = (1, 2)
TypeError: Class.min_max() missing 1 required positional argument: 'max'
вот такой вот код:
class Class:
def __init__(self, min, max):
self.__min = min
self.__max = max
@property
def min_max(self):
return self.__max
@min_max.setter
def min_max(self, min, max):
self.__max = max
self.__min = min
pt = Class(0, 10)
pt.min_max = (1, 2)
print(pt.min_max)
print(pt.__dict__)
эту конкретику лучше спрашивать в сообществе телеграм-канала по Python (ссылка под видео)
спасибо
А вообще - странная конструкция получается. Приватные атрибуты подразумевают отсутствие доступа к ним извне. Но мы делаем "property", в результате чего получаем доступ к приватным атрибутам извне. Т.е. делам приватный атрибут публичным.
зато теперь можно наложить логику изменения или чтения приватного значения. В публичном можно было бы поменять на любое значение, а тут теперь можем наложить какое-нибудь условие
Ну во-первых, ту же логику расширить на protected аргументы. Во-вторых в этой же логике вы можете докрутить дополнительные проверки, эксепшны и так далее
👍
Почему когда мы обращаемся к сеттеру, через оператор присваивания = происходит вызов функции. У меня одно объяснение он переопределен в классе property и выполняет другое действие как скобочки (). По аналогии с переопределением __add__, когда + будет делать заданный функционал а не сложение/конкатенацию. Я прав?
не понял до конца вопроса, может поможет то, что объекты-свойства имеют при обращении более высокий приоритет, чем обычный атрибуты-переменные
Спасибо! А если всё то же самое нужно и для переменной __name, то неужели придётся дублировать код?
Тоже очень интересует. Я попробовал продублировать декораторы для переменной __name и значения переменных в консоли стали равны (__old == __name ).
Только def old надо менять на def name. @property def name(self); return self.__name; @name.setter def name(self, value); self.__name = value
@@TheLazyEagle собственно, я так и предполагал, что не есть круто, по моему мнению.
совершенно верно, придется дублировать, поэтому когда много разных свойств, то лучше использовать уже дескрипторы, речь о них далее )
@@gienek_mscislawski Ну да, если очень много приватных переменных, то код начинает расти.
на данный момент не понятно почему нужно использовать приватные атрибуты, если их можно спокойно изменять при помощи сеттера или проперти?
пока только пришло в голову в геттер или сеттер добавить проверку пароля, например добавить инпут введите кодовое слово и если есть совпадение, то можно извлечь или переопределить свойство...
меняете ширину окна, тогда дополнительно, например, можете в сеттере проверить, что это число и оно положительное
@@selfedu_rus спасибо! нужно практиковать
Получается, к методам с одинаковым именем применяются разные декораторы, которые делают из метода объект property. Интерпретатор понимает какой метод исполнять, в зависимости какой оператор был использован: оператор присвоения - setter, оператор del - deleter, без оператора - getter?
имя метода - это лишь ссылка на объект-функцию класса, поэтому все эти ссылки просто сохраняются в декораторах.
@@AntonyKondr я имел ввиду при вызове в глобальном пространстве имен
@@zakirovio вероятно тут все завязано на сигнатуры.
Вы можете без всяких классов написать кучу просто функций с одинаковым именем но разными аргументами на вход - интерпретатор посчитает их как разные функции и будет выбирать исходя из ситуации нужную.
Рызные декораторы над объявленной функцией так же меняют сигнатуру, получается похожая логика
@@lemonade0224при определении множества функций с одинаковыми именами, вызываться будет только последняя, ее область видимости будет перекрывать другие
объект класса property скорее всего имеет доступ к ссылкам этих одноименных методов и при использовании определенного оператора или инструкции применяет setter. getter или deleter
Сергей, можно ли через property setter изменять два атрибута одновременно, например имеем две стороны прямоугольника А и В. В примере у Вас нужно делать свойство на каждый атрибут, а чисто логично бы сделать одной свойство к на обе стороны прямоугольника... Спасибо заранее.
да, можно, если аргументом передавать кортеж, а в функции его значения присваивать соответствующим свойствам объекта
@@selfedu_rus а Вы не могли бы кусочек такого кода на обозрение представить, пожалуйста))
class Rectangle:
def __init__(self, *nums):
self.__a = nums[0]
self.__b = nums[1]
self.__area = None
@property
def area(self):
if self.__area == None:
self.__area = self.__a * self.__b
return self.__area
@property
def Rect(self):
return self.__a, self.__b
@Rect.setter
def Rect(self, nums):
self.__a = nums[0]
self.__b = nums[1]
self.__area = None
@@Grigorev84
Подскажите, пожалуйста, почему в сеттере вы используете nums, а не *nums?
вам надо записать видео по терминам в ооп, что такое атрибуты свойства, поля, методы, обькты, экземпляры, классы, так людям будет проще)
Первые два видео как раз об этом
етишкин кот!
День добрый, уважаемый Сергей есть вопрос. А property в 5 подвиге нам пришлось как бы дублировать отдельно для width и height тоесть получилось для одного сетер и гетер и для другого сетер и геттер а нельза было для двух обьектов-свойств записать один геттер и сеттер или для каждого объекта свойства должен быть отдельный геттер и сеттер?
Можно и одно, тогда передавать придется сразу два значения как кортеж и читать тоже в виде кортежа.
Спасибо за видео, все очень понятно, но есть вопрос: можно ли таким образом в сеттер передать два значения?
Допустим у на с класс Poіnt, у точки две координаты, можно через @property задават два значения?
да, можно, например, через кортеж
@@selfedu_rusспасибо, сработало
Сергей, сколько вы занимаетесь питоном? Интересно знать сколько нужно заниматься, чтоб так знать
И спасибо вам за уроки, ваш труд неоценим
Спасибо! Я два года с ним знаком. Но здесь важен еще прежний опыт программирования, те кто уже знает другие языки быстрее изучают новые, т.к. много похожего ))
не очень все-таки понятно зачем нужен этот декоратор. Получается, что с помощью него осуществляется доступ к защищенным свойствам. Но можно просто убрать двойное нижнее подчеркивание впереди и получится тот же эффект, без нагромождения сеттеров и геттеров. Разве что в самих этих функциях можно вставлять дополнительные условия проверки на присвоение определенных значений.
см. курс по Django и Flask - там они на каждом шагу ))
Добрый день, Сергей. Подскажите, вы планируете этот курс загружать на Stepik?
Пока нечего загружать ) Проработка курса - это около месяца упорной, рутиной работы. Сейчас не до этого.
Не понял этого
old = property()
old = old.setter(set_get)
old = old.getter(get_old)
Как там присвоение идет...
Здесь нет никакого присваивания, всего лишь применяется декоратор setter к функции set_get и декоратор getter к функции get_old, чтобы обеспечить работу свойства old
Добрый день.
Вопрос, касающийся свойства property.
Правильно ли я понимаю, что имеет значение порядок методов, указанных в свойстве property:
на первом месте всегда метод, обеспечивающий получение значения атрибута,
на втором - метод для задания значения атрибута,
на третьем - метод для удаления значения атрибута,
на четвертом - строка, содержащая документацию?
property(getx, setx, delx, "I am the property.")
И при изменении значения атрибута интерпретатор понимает, что необходимо вызвать метод, указанный на второй позиции свойства property,
при зачитывании значения атрибута - метод, указанный на первой позиции свойства property
и т.д. ?
вроде, да, верно расписали
Зачем делать два различных сеттера и геттера для двух приватных атрибутов? Разве мы не можем изменять и получать их оба через один сеттер/геттер?
Как ты себе это представляешь?
Теория эволюции инкапсуляции в питоне за 16 минут))))
доброе время суток, у меня вопрос: какой смысл делать переменную age закрытой, если мы по факту делаем с ней абсолютно тоже самое благодаря геттерам и сеттерам и вне кода класса работа с атрибутами никаким образом не меняется. Грубо говоря код из конца видео == тому чтобы переменную не делать закрытой
Идея в том, что теперь есть _возможность_ добавить нужный функционал во время записи/чтения атрибута, при этом пользователи класса (другие объекты/классы которые работают с нашим классом) не должны знать об этом, им это неважно. Они просто работают со свойствами, а мы, как создатели нашего класса можем эти свойства проверять, применять, обрабатывать любым нужным способом. Без гетера/сетера т.е. без этой дополнительной прослойки никакой возможности проверить что пишется в проперти и что оттуда достается - нет.
Пример в видео несколько искусственный (потому что нет реальной задачи и в гетера и сетерах действительно ничего не делается) но при этом полностью достаточный для того чтобы показать как работает этот механизм в питоне. Это пример инкапсуляции.
@@osman3d я уже понял это на момент написания вашего комментария, просто сам недавно до классов дошел и на каждом из встреченных мною гайдов с ютуба толком тема закрытых переменных не растолкована. Спасибо за ответ в любом случае и знайте что вы абсолютно правы, на момент написания комментария я в классах не понимал ровным счетом ничего
"Если в классе задан атрибут как объект-свойство, то в первую очередь выбирается оно...", a как тогда обратиться к локальному атрибуту с таким же именем?
только напрямую через __dict__, но обычно это не требуется, для этого и создается объект-свойство
Здравствуйте, много где облазил - ничего не нашел. Надеюсь вы ответите.Почему мы не можем просто сразу создать метод private, почему нужно создавать публичный, а потом в нем делать return private. Вот допустим:
@property
def lvl(self):
return self.__lvl, f'{dt.now() - self.__born}'
@lvl.setter
def lvl(self,numer):
self.__lvl += numer
Почему нельзя сразу создать def __lvl(self)?
Заранее спасибо!
приватные атрибуты - это служебные (как правило, переменные) внутри класса и менять их извне не предполагается. Но если все же нужно получать или менять их значения, то прописывают сеттеры/геттеры или объекты-свойства, где выполняют дополнительную проверку на правильность передачи значений. Подробнее вам могут ответить в телеграм-канале по Python.
не увидел в прошлом видео объяснение гетеров и сетеров. Какое именно?
вспомнил
th-cam.com/video/RipfqbH0eqY/w-d-xo.html
Сергей, подскажите, если использовать property и не использовать атрибуты типа _ _private , то возникает ошибка так как у нас не будет присутствовать свойство , которое мы сделали с помощью property. К примеру у меня будет отсутствовать свойство health
class Player:
def __new__(cls, *args, **kwargs):
print(f'Вызов метода __new__')
return object.__new__(cls)
def __init__(self,name, health, lvl):
self.name = name
self.health = health
self.lvl = lvl
@property
def health(self):
return self.health
@health.setter
def health(self, value):
if value in (int,float):
self.health = value
# else:
# raise TypeError('Здоровье должно быть написано цифрами')
#
p1= Player('Henry', 100, 5)
print(p1.__dict__)
print(p1.health) ---- > ОШИБКА
Получается чтобы использовать объект свойство нужно чтобы свойства быти всегда или protected или private?
Посмотрел 4 минуты и не понимаю, в чём практический/сакральный/иной смысл этих манипуляций?
Сначала мы сделали атрибуты приватными, затем расприватили их, чтобы иметь возможность обращаться к ним.
Для чего?
print(class_name.__dict__) показывает все наши "приватные" данные
Единственное, что удобно = old = property(get_old, set_old), как дальнейшее использование чтения/записи используя прдемонстрированный в видео подход.
Но стоит ли оно того, чтобы каждый раз это прописывать?
тоже не понял.
После стиля C# стиль ООП пихтона смотрится конечно дико
спасибо) но если можно чуть помедленнее
Что такое объект свойства, в этой теме про него говорят, но я никак не могу понять
@property
Касаемо функционального дублирования. Почему бы вместо докорирования геттеров и сеттеров не сделать сами геттеры и сеттеры приватными, и передавать в объект property приватные геттеры и сеттеры?
Зачем делать атрибут приватным, чтобы потом сделать пубоичным, каким он был изначально?
Через property можно контролировать, что записываем и что отдаем.
@@selfedu_rus благодарю
Всего один сеттер и все, тебе уже 35
Вот эта конструкция не ясна
old = property()
old = old.setter(set_old)
old = old.getter(get_old)
Больно уж похоже на оверрайд одного и того же атрибута разными объектами
BTW
Вот такое вот
old = property(get_old, set_old)
Было бы понятнее
все равно не понимаю, зачем мы запрещаем программисту обращаться к свойствам объекта напрямую:
p.old
а потом городим еще кучу строчек, чтобы он все-таки потом мог обращаться к свойствам объекта визуально и по сути будто напрямую:
p.old
Почему бы нам сразу не разрешить ему иметь доступ к свойству напрямую?
Интересно, мы добавили "__" чтобы было нельзя взаимодействовать с атрибутом, а потом делаем так, что бы ми могли
да, но мы же не напрямую теперь с ним работаем, а через методы, а в методах можно дополнительные проверки выполнять
очень всё сложно и запутанно. как это всё запомнить, решительно непонятно.
В чем смысл такого функционала? Приватизировать, потом создавать декораторы, чтоб обращаться к методам класса, в чем смысл можете объяснить, чтоб я понимал в чем была цель такой логики в классах?
одно через другое через третье, фиг знает что., А где бл... постулаты пайтона - явное лучше неявного, Простое - лучше сложного. вопрос - нахера тьак все усложнять , мало вижу пользы в этом все по итогу Только голову ломать
Разве self.__name = name это локальное свойство а не приватный атрибут?
th-cam.com/video/MxviMwbGl3I/w-d-xo.htmlm00s,
это и локальное свойство и приватный атрибут )
Бесполезная хрень
Только кода больше
.
Написали одно потом написали второе в итоге и то и другое есть.
Я бы назвал поле old не свойство класса , а лямбда функция , которая работает двояко , в зависимости от чтения или записи. Просто очень похоже на поведение лямбда функции 🤔
если честно - какого то облегчения так и не увидел. Вроде и без проперти всё прекрасно работает. Объём кода сильно не уменьшился
удобство в дальнейшем применении класса, конечно, если property выполняет не банальное присваивание, а некий алгоритм
Спасибо за видео!
спасибо!!