Простой Python. Современный стиль программирования (Любанович) - страница 91

>>>> c.diameter = 20

>Traceback (most recent call last):

>··File "", line 1, in

>AttributeError: can't set attribute

У использования свойств вместо непосредственного доступа к атрибутам имеется еще одно преимущество: если вы измените определение атрибута, вам нужно будет поправить только код внутри определения класса вместо того, чтобы править все вызовы.

Искажение имен для безопасности

В примере с классом Duck из предыдущего раздела мы вызывали наш (не полностью) скрытый атрибут hidden_name. Python предлагает соглашения по именованию для атрибутов, которые не должны быть видимы за пределами определения их классов: имена начинаются с двух нижних подчеркиваний (__).

Переименуем атрибут hidden_name в __name, как показано здесь:

>>>> class Duck():

>…·····def __init__(self, input_name):

>…·········self.__name = input_name

>…·····@property

>…·····def name(self):

>…·········print('inside the getter')

>…·········return self.__name

>…·····@name.setter

>…·····def name(self, input_name):

>…·········print('inside the setter')

>…·········self.__name = input_name

>…

Теперь проверим, работает ли все как полагается:

>>>> fowl = Duck('Howard')

>>>> fowl.name

>inside the getter

>'Howard'

>>>> fowl.name = 'Donald'

>inside the setter

>>>> fowl.name

>inside the getter

>'Donald'

Выглядит хорошо. И вы не можете получить доступ к атрибуту __name:

>>>> fowl.__name

>Traceback (most recent call last):

>··File "", line 1, in

>AttributeError: 'Duck' object has no attribute '__name'

Это соглашение по именованию не делает атрибут закрытым, но Python искажает имя для того, чтобы внешний код не наткнулся на него. Если вам любопытно и вы никому не расскажете, я покажу вам, как будет выглядеть атрибут:

>>>> fowl._Duck__name

>'Donald'

Обратите внимание на то, что на экране не появилась надпись inside the getter. Хотя эта защита не идеальна, искаженное имя отказывается случайно или намеренно получать доступ к атрибуту.

Типы методов

Одни данные (атрибуты) и функции (методы) являются частью самого класса, а другие — частью объектов, которые созданы на его основе.

Когда вы видите начальный аргумент self в методах внутри определения класса, этот метод является методом экземпляра. Такие методы вы обычно пишете при создании собственного класса. Первый параметр метода экземпляра — это self, и Python передает объект методу, когда вы его вызываете.

В противоположность ему метод класса влияет на весь класс целиком. Любое изменение, которое происходит с классом, влияет на все его объекты. Внутри определения класса декоратор @classmethod показывает, что следующая функция является методом класса. Первым параметром метода также является сам класс. Согласно традиции этот параметр называется cls, поскольку слово class является зарезервированным и не может быть использовано здесь. Определим метод класса для А, который будет подсчитывать количество созданных объектов: