property и __slots__

Два прикладных вопроса по ООП: управляемые атрибуты через property и экономия памяти через __slots__.

@property превращает метод в «вычисляемый атрибут»: доступ как к полю, но с логикой внутри. __slots__ ограничивает набор атрибутов и убирает у объекта словарь __dict__.

property: атрибут с логикой и валидацией

Чёткий ответ. property позволяет обращаться к методу как к атрибуту (obj.x вместо obj.x()) и добавить проверку при чтении/записи, не меняя внешний интерфейс.

class Celsius:
    def __init__(self, t=0):
        self._t = t

    @property
    def temperature(self):
        return self._t

    @temperature.setter
    def temperature(self, value):
        if value < -273.15:
            raise ValueError("ниже абсолютного нуля")
        self._t = value

    @property
    def fahrenheit(self):              # вычисляемый атрибут
        return self._t * 9 / 5 + 32

c = Celsius(25)
print("по Фаренгейту:", c.fahrenheit)
c.temperature = 100                    # вызовет setter с проверкой
print("по Фаренгейту:", c.fahrenheit)

Вывод:

по Фаренгейту: 77.0
по Фаренгейту: 212.0

Снаружи c.fahrenheit выглядит как обычное поле, но считается на лету. А запись в c.temperature проходит через проверку — попытка задать значение ниже абсолютного нуля вызовет ошибку.

__slots__: меньше памяти, фиксированный набор полей

По умолчанию атрибуты объекта хранятся в словаре __dict__ — это гибко, но затратно по памяти. __slots__ объявляет жёсткий список полей: словарь не создаётся, экземпляры легче, а добавить новый атрибут уже нельзя.

class WithSlots:
    __slots__ = ("x", "y")             # разрешены только x и y

    def __init__(self, x, y):
        self.x, self.y = x, y

w = WithSlots(1, 2)
print(w.x, w.y)
try:
    w.z = 3                            # нового поля нет в слотах
    print("z добавлен")
except AttributeError:
    print("нельзя добавить атрибут z")

Вывод:

1 2
нельзя добавить атрибут z

Когда что применять

  • @property — когда нужен контроль доступа или вычисляемое поле, сохранив простой интерфейс obj.attr.
  • __slots__ — когда создаётся очень много мелких объектов и важна память (например, миллионы точек).

Итог

  • @property даёт доступ к методу как к атрибуту и место для валидации в setter.
  • __slots__ убирает __dict__, экономит память и фиксирует список атрибутов.
  • В классе со __slots__ нельзя завести атрибут, которого нет в списке.
Проверьте себя
1. Что делает @property?
AДелает атрибут приватным
BПозволяет обращаться к методу как к атрибуту и добавить логику доступа
CУскоряет класс
DСоздаёт статический метод
2. Что даёт __slots__?
AДелает класс быстрее в наследовании
BУбирает __dict__, экономит память и фиксирует набор атрибутов
CРазрешает любые атрибуты
DВключает многопоточность
3. Что произойдёт при попытке задать атрибут вне __slots__?
AОн создастся в __dict__
BБудет AttributeError
CПрограмма зависнет
DАтрибут проигнорируется молча
Поддержать проект