Цей контент є частиною серії:
Слідкуйте за виходом нових статей цієї серії.
Ми продовжуємо вивчати класи в Python. Спеціальні зарезервовані методи тут мають префікс - подвійний символ підкреслення. З їх допомогою реалізовані такі механізми, як конструктори, послідовності, ітератори, проперти, слоти і т.д.
Сьогодні ми розглянемо такі теми.
- Об'єкти класів і спеціальні методи.
- Примірники класів і спеціальні методи.
- Примірники класів в якості послідовностей.
- Приведення об'єктів до базових типів.
- Bound і unbound методи.
- Метод super.
- Статичні методи.
- Итератор.
- Property.
- Singleton.
- Слоти.
- Функтор.
- Дескриптор.
- Sequence.
1. Об'єкти класів і спеціальні методи
Об'єкт-клас створюється за допомогою визначення класу. Об'єкти-класи мають наступні атрибути:
__name__ - ім'я класу;
__module__ - ім'я модуля;
__dict__ - словник атрибутів класу, можна змінювати цей словник безпосередньо;
__bases__ - кортеж базових класів в порядку їх слідування;
__doc__ - рядок документації класу.
2. Примірники класів і спеціальні методи
Примірник (інстанси) класу повертається при виклику об'єкта-класу. Об'єкт у класу може бути один, примірників (або інстанси) - кілька. Примірники мають наступні атрибути:
__dict__ - словник атрибутів класу, можна змінювати цей словник безпосередньо;
__class__ - об'єкт-клас, екземпляром якого є даний інстанси;
__init__ - конструктор. Якщо в базовому класі є конструктор, конструктор похідного класу повинен викликати його;
__del__ - деструктор. Якщо в базовому класі є деструкор, деструктор похідного класу повинен викликати його;
__cmp__ - викликається для всіх операцій порівняння;
__hash__ - повертає хеш-значення об'єкта, що дорівнює 32-бітного числа;
__getattr__ - повертає атрибут, недоступний звичайним способом;
__setattr__ - привласнює значення атрибуту;
__delattr__ - видаляє атрибут;
__call__ - спрацьовує при виклику екземпляра класу.
3. Примірники класів в якості послідовностей
Примірники класів можна використовувати для емуляції послідовностей. Для такої реалізації є вбудовані методи:
__len__ - повертає довжину послідовності;
__getitem__ - отримання елемента за індексом або ключу;
__setitem__ - присвоювання елементу з даними ключем або індексом;
__delitem__ - видалення елемента з даними ключем або індексом;
__getslice__ - повертає вкладену послідовність;
__setslice__ - замінює вкладену послідовність;
__delslice__ - видаляє вкладену послідовність;
__contains__ - реалізує оператор in.
4. Приведення об'єктів до базових типів
Об'єкти класів можна привести до строковому або числового типу.
__repr__ - повертає формальне строкове представлення об'єкту;
__str__ - повертає строкове представлення об'єкту;
__oct__. __hex__. __complex__. __int__. __long__. __float__ - повертають строкове представлення у відповідній системі числення.
5. Bound і unbound методи
Розглянемо конкретний приклад. Є базовий клас Cat, і є похідний від нього клас Barsik:
Створюємо примірник похідного класу:
На перший погляд - дивна помилка, оскільки атрибут hungry є в базовому класі. Насправді, конструктор похідного класу - перевантажений, при цьому конструктор базового класу не викликається, і його потрібно явно викликати. Це можна зробити двома шляхами. Перший варіант вважається застарілим:
6. Метод super
Другий варіант: на початку програми потрібно визначити метаклассом. який вказує на те, що клас реалізований в так званому новому стилі - new-style. Потім потрібно викликати стандартний метод super для базового конструктора:
7. Статичні методи
Статичний метод - функція, певна поза класом і не має атрибута self:
Статичний метод може бути визначений і всередині класу - для цього використовується ключове слово staticmethod. причому метод може бути викликаний як статично, так і через інстанси:
Методи класу визначаються за допомогою ключового слова classmethod - тут автоматично пітон передає в якості першого параметра сам клас (cls):
8. Итератор
Ітератори гарні там, де списки не підходять в силу того, що займають багато пам'яті, а итератор повертає його конкретне значення. У класі потрібно визначити два стандартних методу - __iter__ і next. Метод __iter__ буде повертати об'єкт через метод next:
Итератор можна конвертувати в список:
9. Property
Property - атрибут класу, що повертається через стандартну функцію property, яка в якості аргументів приймає інші функції класу:
10. Singleton
Даний патерн дозволяє створити всього один інстанси для класу. Використовується метод __new__:
Слоти - це список атрибутів, що задається в заголовку класу за допомогою __slots__. У інстанси необхідно призначити атрибут, перш ніж користуватися ним:
12. Функтор
Функтор - це клас, який має метод __call__ - при цьому об'єкт можна викликати як функцію.
Приклад. Нехай у нас є клас Person, є колекція об'єктів цього класу-people, потрібно впорядкувати цю колекцію за прізвищами. Для цього можна використовувати функтор Sortkey:
13. Дескриптор
Дескриптор - це клас, який зберігає і контролює атрибути інших класів. Взагалі будь-який клас, який імплементує один зі спеціальних методів - __get__. __set__. __delete__. є дескриптором.
В даному випадку клас Point не має власних атрибутів x, y, хоча викликає їх так, як ніби вони є - насправді вони зберігаються в дескрипторі ExternalStorage.
14. Sequence
Послідовність реалізується за допомогою методів __getitem__. __setitem__. В даному прикладі клас MySequence повертає за індексом елемент послідовності невизначеної довжини, що представляє собою арифметичну прогресію види: 1 3 5 7. Тут не можна застосувати стандартні методи __del__. __len__:
висновок
Сьогодні ми дізналися, що класи в Пітоні мають великий набір вбудованих методів і атрибутів, які дозволяють гнучко використовувати модель об'єктно-орієнтованого програмування і спрощують рішення стандартних завдань і алгоритмів. Методи можуть бути статичними в залежності від природи об'єкта, що дозволяє змішувати об'єктно-орієнтовану і функціональну архітектуру. Виклик методів базового класу має власну семантику. Послідовності і мапи, реалізовані на базі ітераторів, економлять ресурси і пам'ять. Проперті спрощують складну реалізацію атрибутів класу. Функтори звертаються з колекцією об'єктів користувальницького типу так, як ніби це стандартні типи. Дескриптори реалізують різну логіку зберігання атрибутів класу. В продовження циклу розповімо про роботу з файловою системою засобами Python.
Код прикладів перевірений на версії пітона 2.6.