Классы

Классы - это ядро Python. Они дают широкие возможности, но их легко неправильно использовать. В этой главе я расскажу про некоторые трюки в работе с классами и сделаю несколько предостережений. Давайте начнем!

Переменные экземпляра и класса

Большинство начинающих, а иногда и опытных Python разработчиков не понимают до конца различия между переменными экземпляра и переменными класса. Это приводит к некорректному использованию этих различных типов переменных. Давайте разберемся.

Основное различие:

  • Переменные экземпляров предназначены для данных уникальных для каждого

    объекта

  • Переменные класса - для общих для всех экземпляров класса данных

Посмотрим на пример:

class Cal(object):
    # pi - переменная класса
    pi = 3.142

    def __init__(self, radius):
        # self.radius - переменная экземпляра
        self.radius = radius

    def area(self):
        return self.pi * (self.radius ** 2)

a = Cal(32)
a.area()
# Вывод: 3217.408
a.pi
# Вывод: 3.142
a.pi = 43
a.pi
# Вывод: 43

b = Cal(44)
b.area()
# Вывод: 6082.912
b.pi
# Вывод: 3.142
b.pi = 50
b.pi
# Вывод: 50

С использованием изменяемых переменных класса редко бывают проблемы. Поэтому разработчики обычно не стараются изучить тему подробнее - все и так работает! Если вы тоже уверены в надежности использования таких переменных, то следующий пример для вас:

Красота неправильного использования изменяемых переменных класса. Для предотвращения подобных ошибок - не храните изменяемые структуры данных в переменных класса или понимайте зачем вам это нужно.

Классы нового стиля

Классы нового стиля были представлены в Python 2.1, но не так много разработчиков знает о них даже сейчас! Отчасти это связано с сохранением поддержки классов старого стиля для обратной совместимости. Давайте рассмотрим разницу между двумя стилями:

  • Классы старого стиля ничему не наследуют

  • Классы нового стиля наследуют object

Базовый пример:

Наследование от object дает новым классам доступ к определенной магии. Например, вы можете использовать оптимизацию __slots__, вызов super() и дескрипторы. Резюме? Всегда используйте классы нового стиля.

Примечание: в Python 3 все классы нового стиля. Не важно наследует ли ваш класс object или нет. Тем не менее, хорошей идеей будет явно прописывать наследование.

Магические методы

Классы в Python известны за свои магические методы, их отличительная черта - двойное нижнее подчеркивание с двух сторон от имени. Давайте рассмотрим несколько из них.

__init__

Это конструктор класса. Конструктор вызывается каждый раз при создании экземпляра класса. Например:

Как вы видите __init__ вызывается при создании экземпляра класса. Вы также можете передавать аргументы конструктору для инициализации экземпляра:

Надеюсь в общих чертах логика работы __init__ понятна.

__getitem__

Реализация метода __getitem__ в классе позволяет использовать на его экземплярах [] оператор. Пример:

Без реализации __getitem__ вы бы получили следующую ошибку:

Last updated