Читаем Простой Python онлайн бесплатно

Обратите внимание на то, что на экране не появилась надпись 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.

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