Специальные (Магические) Методы
В Python существуют методы со специальными именами, которые начинаются и заканчиваются двойным подчеркиванием (например, __init__, __str__). Их называют магическими или dunder (double underscore) методами.
Они не предназначены для прямого вызова (обычно вы не пишете my_object.__str__()). Вместо этого Python вызывает их автоматически в ответ на определенные операции или встроенные функции. Они позволяют настраивать поведение объектов вашего класса, чтобы они работали с операторами и функциями Python ожидаемым образом.
Основные Специальные Методы:
__init__(self, ...): Инициализатор объекта (конструктор). Вызывается при создании экземпляра (MyClass(...)).__str__(self): Возвращает неформальное, удобочитаемое строковое представление объекта. Вызывается функциейprint()иstr(). Если не определен,print()использует__repr__.__repr__(self): Возвращает официальное, однозначное строковое представление объекта, которое в идеале позволяет воссоздать объект (eval(repr(obj)) == obj). Вызывается, когда объект отображается в интерактивной консоли, а также функциейrepr(). Если__str__не определен, используется__repr__. Рекомендуется всегда определять__repr__.__len__(self): Возвращает “длину” объекта. Вызывается функциейlen().__add__(self, other): Позволяет использовать оператор+с объектами (obj1 + obj2).__sub__(self, other): Оператор-.__mul__(self, other): Оператор*.__eq__(self, other): Позволяет использовать оператор сравнения - (obj1 == obj2).__lt__(self, other): Оператор<(меньше чем).__le__(self, other): Оператор<=(меньше или равно).__gt__(self, other): Оператор>(больше чем).__ge__(self, other): Оператор>=(больше или равно).__getitem__(self, key): Позволяет обращаться к элементам объекта по индексу или ключу (obj[key]).__setitem__(self, key, value): Позволяет присваивать значения элементам по индексу или ключу (obj[key] = value).__delitem__(self, key): Позволяет удалять элементы по индексу или ключу (del obj[key]).__call__(self, ...): Позволяет “вызывать” объект как функцию (obj(...)).
class Book:
def __init__(self, title, author, pages):
self.title = title
self.author = author
self.pages = pages
# Неформальное представление для пользователя
def __str__(self):
return f'"{self.title}" автора {self.author}'
# Официальное представление для разработчика
def __repr__(self):
return f"Book(title='{self.title}', author='{self.author}', pages={self.pages})"
# Длина книги - количество страниц
def __len__(self):
return self.pages
# Сравнение книг по количеству страниц
def __eq__(self, other):
if isinstance(other, Book):
return self.pages == other.pages
return NotImplemented
def __lt__(self, other):
if isinstance(other, Book):
return self.pages < other.pages
return NotImplemented
book1 = Book("Война и Мир", "Л. Толстой", 1225)
book2 = Book("Гарри Поттер", "Дж. Роулинг", 400)
print(book1) # Вызывает __str__: "Война и Мир" автора Л. Толстой
print(str(book1)) # Вызывает __str__: "Война и Мир" автора Л. Толстой
print(repr(book1)) # Вызывает __repr__: Book(title='Война и Мир', author='Л. Толстой', pages=1225)
print(len(book1)) # Вызывает __len__: 1225
print(book1 == book2) # False (__eq__)
print(book1 > book2) # True (__lt__ определяет и > через отражение)7.2. Свойства (@property)
Декоратор @property позволяет определить метод, который будет доступен как атрибут (без вызова через скобки ()). Это основной “питоничный” способ реализации геттеров, сеттеров и делитеров, позволяющий контролировать доступ к атрибутам и добавлять логику при их чтении, записи или удалении.
- Геттер (
@property): Метод, декорированный@property, выполняется при чтении атрибута. - Сеттер (
@attribute_name.setter): Метод, декорированный сеттером свойства, выполняется при попытке присвоить значение атрибуту. Позволяет добавить валидацию. - Делитер (
@attribute_name.deleter): Метод, декорированный делитером свойства, выполняется при попытке удалить атрибут (del obj.attribute).
class Product:
def __init__(self, name, price):
self.name = name
# Используем сеттер при инициализации для валидации
self.price = price
@property
def price(self):
# Этот метод вызывается при чтении obj.price
print(f"Получение цены для {self.name}")
return self._price # Возвращаем значение из "приватного" атрибута
@price.setter
def price(self, value):
# Этот метод вызывается при присваивании obj.price = value
print(f"Установка цены {value} для {self.name}")
if value < 0:
raise ValueError("Цена не может быть отрицательной")
# Сохраняем значение в "приватном" атрибуте (с подчеркиванием)
self._price = value
@price.deleter
def price(self):
# Этот метод вызывается при del obj.price
print(f"Удаление цены для {self.name}")
del self._price
# Создаем объект, сеттер вызывается из __init__
item = Product("Ноутбук", 50000)
# Вывод: Установка цены 50000 для Ноутбук
# Читаем цену - вызывается геттер (@property)
current_price = item.price
# Вывод: Получение цены для Ноутбук
print(f"Текущая цена: {current_price}") # 50000
# Изменяем цену - вызывается сеттер (@price.setter)
item.price = 55000
# Вывод: Установка цены 55000 для Ноутбук
# Попытка установить невалидную цену
try:
item.price = -100
except ValueError as e:
print(e) # Вывод: Цена не может быть отрицательной
# Удаляем цену - вызывается делитер (@price.deleter)
del item.price
# Вывод: Удаление цены для Ноутбук
# print(item.price) # AttributeError: _price (атрибут был удален)Использование свойств позволяет сохранить простой синтаксис доступа к атрибутам (obj.price), но при этом добавить сложную логику или валидацию при необходимости. Имя “приватного” атрибута (_price) обычно начинается с одного подчеркивания.
〰〰〰 𓆝 𓆟 𓆞 𓆝 𓆟 𓆝 𓆟 𓆞 〰〰〰