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

<p>Типы методов</p>

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

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

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

>>> class A():

…·····count = 0

…·····def __init__(self):

…·········A.count += 1

…·····def exclaim(self):

…·········print("I'm an A!")

…·····@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.

Третий тип методов не влияет ни на классы, ни на объекты: он находится внутри класса только для удобства вместо того, чтобы располагаться где-то отдельно. Это статический метод, перед которым располагается декоратор @staticmethod, не имеющий в качестве начального параметра ни self, ни класс class. Рассмотрим пример, который служит в качестве рекламы класса CoyoteWeapon:

>>> class CoyoteWeapon():

…·····@staticmethod

…·····def commercial():

…·········print('This CoyoteWeapon has been brought to you by Acme')

>>>

>>> CoyoteWeapon.commercial()

This CoyoteWeapon has been brought to you by Acme

Обратите внимание на то, что нам не нужно создавать объект класса CoyoteWeapon, чтобы получить доступ к этому методу. Это здорово.

<p>Утиная типизация</p>

В Python имеется также реализация полиморфизма — это значит, что одна операция может быть произведена над разными объектами независимо от их класса.

Используем уже знакомый нам инициализатор __init__() для всех трех классов Quote, но добавим две новые функции:

• who() возвращает значение сохраненной строки person;

• says() возвращает сохраненную строку words, имеющую особую пунктуацию.

Посмотрим на них в действии:

>>> class Quote():

…·····def __init__(self, person, words):

…·········self.person = person

…·········self.words = words

…·····def who(self):

…·········return self.person

…·····def says(self):

…·········return self.words + '.'

>>> class QuestionQuote(Quote):

…······def says(self):

…··········return self.words + '?'

>>> class ExclamationQuote(Quote):

…······def says(self):

…··········return self.words + '!'

>>>

Мы не меняли способ инициализации классов QuestionQuote и ExclamationQuote, поэтому не перегружали их методы __init__(). Далее Python автоматически вызывает метод __init__() родительского класса Quote, чтобы сохранить переменные объекта person и words. Поэтому мы можем получить доступ к атрибуту self.words в объектах, созданных с помощью подклассов QuestionQuote и ExclamationQuote.

Далее создадим несколько объектов:

>>> hunter = Quote('Elmer Fudd', "I'm hunting wabbits")

>>> print(hunter.who(), 'says:', hunter.says())

Elmer Fudd says: I'm hunting wabbits.

Перейти на страницу:

Все книги серии Бестселлеры O'Reilly

Похожие книги