>>> fowl.__name
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Duck' object has no attribute '__name'
Это соглашение по именованию не делает атрибут закрытым, но Python иска-
жает имя для того, чтобы внешний код не наткнулся на него. Если вам любопытно
и вы никому не расскажете, я покажу вам, как будет выглядеть атрибут:
>>> fowl._Duck__name
'Donald'
Обратите внимание на то, что на экране не появилась надпись inside the getter.
Хотя эта защита не идеальна, искаженное имя отказывается случайно или наме-
ренно получать доступ к атрибуту.
Типы методов
Одни данные (атрибуты) и функции (методы) являются частью самого класса,
а другие — частью объектов, которые созданы на его основе.
Когда вы видите начальный аргумент self в методах внутри определения клас-
са, этот метод является методом экземпляра. Такие методы вы обычно пишете при
создании собственного класса. Первый параметр метода экземпляра — это self,
и Python передает объект методу, когда вы его вызываете.
В противоположность ему метод класса влияет на весь класс целиком. Любое
изменение, которое происходит с классом, влияет на все его объекты. Внутри опре-
деления класса декоратор @classmethod показывает, что следующая функция являет-
ся методом класса. Первым параметром метода также является сам класс. Согласно
традиции этот параметр называется cls, поскольку слово class является зарезер-
вированным и не может быть использовано здесь. Определим метод класса для А,
который будет подсчитывать количество созданных объектов:
>>> class A():
... count = 0
... def __init__(self):
... A.count += 1
... def exclaim(self):
... print("I'm an A!")
170
Глава 6. Ой-ой-ой: объекты и классы
... @classmethod
... def kids(cls):
... print("A has", cls.count, "little objects.")
...
>>>
>>> easy_a = A()
>>> breezy_a = A()
>>> wheezy_a = A()
>>> A.kids()
A has 3 little objects.
Обратите внимание на то, что мы вызвали метод A.count (атрибут класса) вместо
self.count (который является атрибутом объекта). В методе kids() мы использова-
ли вызов cls.count, но с тем же успехом могли бы применять вызов A.count.
Третий тип методов не влияет ни на классы, ни на объекты: он находится внутри
класса только для удобства вместо того, чтобы располагаться где-то отдельно.