0 added
0 removed
Original
2026-01-01
Modified
2026-02-26
1
<p>Представим, что у нас есть такой класс:</p>
1
<p>Представим, что у нас есть такой класс:</p>
2
<p>Что нам делать, если мы захотим иметь возможность получить еще и полное имя (имя+фамилию) объекта?</p>
2
<p>Что нам делать, если мы захотим иметь возможность получить еще и полное имя (имя+фамилию) объекта?</p>
3
<p>Мы могли бы в инициализаторе добавить строчку self.full_name = name + ' ' + surname. Но если впоследствии имя или фамилия поменяются, полное имя устареет, и его нужно будет не забыть поменять.</p>
3
<p>Мы могли бы в инициализаторе добавить строчку self.full_name = name + ' ' + surname. Но если впоследствии имя или фамилия поменяются, полное имя устареет, и его нужно будет не забыть поменять.</p>
4
<p>Также мы могли бы добавить метод с именем вроде get_full_name, который бы возвращал полное имя. Но и такой вариант не идеален, ведь нам хочется работать с полным именем, как с простым атрибутом-переменной.</p>
4
<p>Также мы могли бы добавить метод с именем вроде get_full_name, который бы возвращал полное имя. Но и такой вариант не идеален, ведь нам хочется работать с полным именем, как с простым атрибутом-переменной.</p>
5
<p>Оказывается, что в Python есть средство, позволяющее получить атрибут, значение которого вычисляется<em>динамически</em>, то есть во время обращения к атрибуту. Речь идет о<em>свойствах</em>.</p>
5
<p>Оказывается, что в Python есть средство, позволяющее получить атрибут, значение которого вычисляется<em>динамически</em>, то есть во время обращения к атрибуту. Речь идет о<em>свойствах</em>.</p>
6
<p>Добавим в класс свойство и посмотрим на его использование:</p>
6
<p>Добавим в класс свойство и посмотрим на его использование:</p>
7
<p>full_name выглядит как утка, то есть как атрибут. Но вычисляется динамически. И если мы поменяем name, то full_name также изменится:</p>
7
<p>full_name выглядит как утка, то есть как атрибут. Но вычисляется динамически. И если мы поменяем name, то full_name также изменится:</p>
8
<p>Как вы можете видеть, свойство объявляется как метод без параметров (кроме self, естественно),<em>декорированный</em>с помощью property. Такой метод, возвращающий динамически вычисляемое значение, называется<em>геттером (getter)</em>.</p>
8
<p>Как вы можете видеть, свойство объявляется как метод без параметров (кроме self, естественно),<em>декорированный</em>с помощью property. Такой метод, возвращающий динамически вычисляемое значение, называется<em>геттером (getter)</em>.</p>
9
<h2>Сеттер</h2>
9
<h2>Сеттер</h2>
10
<p>Атрибутам пространства имен можно присваивать значения, но что делать, если атрибут - свойство? Если вы попытаетесь присвоить значение свойству, у которого один лишь getter, вы получите ошибку "AttributeError: can't set attribute".</p>
10
<p>Атрибутам пространства имен можно присваивать значения, но что делать, если атрибут - свойство? Если вы попытаетесь присвоить значение свойству, у которого один лишь getter, вы получите ошибку "AttributeError: can't set attribute".</p>
11
<p>Чтобы иметь возможность присвоить значение свойству, нужно использовать<em>сеттер (setter)</em>. Сеттер - это тоже метод, который принимает новое значение для атрибута и как-то его обрабатывает. Чтобы метод стал сеттером, его тоже нужно соответствующим образом декорировать. Если у вас уже есть геттер, вы можете сделать так:</p>
11
<p>Чтобы иметь возможность присвоить значение свойству, нужно использовать<em>сеттер (setter)</em>. Сеттер - это тоже метод, который принимает новое значение для атрибута и как-то его обрабатывает. Чтобы метод стал сеттером, его тоже нужно соответствующим образом декорировать. Если у вас уже есть геттер, вы можете сделать так:</p>
12
<p>Теперь свойству full_name можно присваивать новое полное имя. В итоге оно будет разделено по пробелу на две части, первая из которых станет новым именем, а вторая - фамилией. Пример:</p>
12
<p>Теперь свойству full_name можно присваивать новое полное имя. В итоге оно будет разделено по пробелу на две части, первая из которых станет новым именем, а вторая - фамилией. Пример:</p>
13
<p>Сеттеры часто используют для того, чтобы проверить корректность нового значения или произвести какие-то его преобразования перед фактическим сохранением в другие атрибуты.</p>
13
<p>Сеттеры часто используют для того, чтобы проверить корректность нового значения или произвести какие-то его преобразования перед фактическим сохранением в другие атрибуты.</p>
14
<h2>Делитер</h2>
14
<h2>Делитер</h2>
15
<p>Кроме геттеров и сеттеров, в Python существует еще один важный метод для управления атрибутами классов - это<em>делитеры (deleter)</em>. Этот метод предоставляет дополнительный уровень контроля над тем, как атрибуты класса удаляются.</p>
15
<p>Кроме геттеров и сеттеров, в Python существует еще один важный метод для управления атрибутами классов - это<em>делитеры (deleter)</em>. Этот метод предоставляет дополнительный уровень контроля над тем, как атрибуты класса удаляются.</p>
16
<p>Делитер - это особый метод в классе, который вызывается при удалении атрибута. Как правило, удаление атрибута - это нечастая операция, и в большинстве случаев мы можем обойтись без явного определения делитера. Тем не менее, зная о его существовании, мы можем контролировать процесс удаления атрибутов, например, очищать связанные ресурсы или выполнять некоторую логику очистки.</p>
16
<p>Делитер - это особый метод в классе, который вызывается при удалении атрибута. Как правило, удаление атрибута - это нечастая операция, и в большинстве случаев мы можем обойтись без явного определения делитера. Тем не менее, зная о его существовании, мы можем контролировать процесс удаления атрибутов, например, очищать связанные ресурсы или выполнять некоторую логику очистки.</p>
17
<p>В нашем примере с классом Person, если мы решим реализовать делитер для свойства full_name, то его можно использовать для удаления имени и фамилии. Давайте посмотрим, как это работает:</p>
17
<p>В нашем примере с классом Person, если мы решим реализовать делитер для свойства full_name, то его можно использовать для удаления имени и фамилии. Давайте посмотрим, как это работает:</p>
18
<p>Теперь при удалении свойства full_name будет вызываться наш делитер, который устанавливает свойствам name и surname значение None, тем самым "удаляя" эти значения. Пример:</p>
18
<p>Теперь при удалении свойства full_name будет вызываться наш делитер, который устанавливает свойствам name и surname значение None, тем самым "удаляя" эти значения. Пример:</p>
19
<p>Использование делитера особенно полезно в случаях, когда необходимо управлять удалением важных или связанных данных, или выполнять освобождение ресурсов (как, например, закрытие файлов или сетевых соединений) в момент уничтожения объекта или его свойств.</p>
19
<p>Использование делитера особенно полезно в случаях, когда необходимо управлять удалением важных или связанных данных, или выполнять освобождение ресурсов (как, например, закрытие файлов или сетевых соединений) в момент уничтожения объекта или его свойств.</p>
20
<h2>Декоратор property</h2>
20
<h2>Декоратор property</h2>
21
<p>Если посмотреть в документацию к декоратору property, то можно увидеть такую сигнатуру:</p>
21
<p>Если посмотреть в документацию к декоратору property, то можно увидеть такую сигнатуру:</p>
22
<p>Первые три аргумента позволяют задать getter, setter и deleter, а аргумент doc позволяет указать docstring. В такой форме property удобно использовать, когда вы уже имеете готовые функции, которые хотите просто "упаковать" в свойство:</p>
22
<p>Первые три аргумента позволяют задать getter, setter и deleter, а аргумент doc позволяет указать docstring. В такой форме property удобно использовать, когда вы уже имеете готовые функции, которые хотите просто "упаковать" в свойство:</p>
23
<p>Также обычный вызов property может пригодиться, если вы будете делать свои декораторы, реализующие какие-то особенные свойства.</p>
23
<p>Также обычный вызов property может пригодиться, если вы будете делать свои декораторы, реализующие какие-то особенные свойства.</p>