Ответ
В Python геттеры создаются с помощью декоратора @property. Они позволяют обращаться к методу класса как к атрибуту, скрывая внутреннюю логику и предоставляя контролируемый доступ на чтение.
Это ключевой механизм инкапсуляции, который используется для:
- Вычисляемых свойств: Создания атрибутов, значение которых зависит от других (например,
full_nameизfirst_nameиlast_name). - Добавления логики при чтении: Например, форматирование данных перед их возвратом.
- Создания атрибутов только для чтения (read-only).
Пример:
class User:
def __init__(self, first_name, last_name):
self._first_name = first_name # Приватный атрибут
self._last_name = last_name
@property
def full_name(self): # Геттер для вычисляемого свойства
"""Возвращает полное имя пользователя."""
return f"{self._first_name} {self._last_name}".title()
# Использование
user = User("john", "doe")
# Обращение как к атрибуту, а не вызов метода user.full_name()
print(user.full_name) # Вывод: John Doe
Ключевые особенности:
- Синтаксис атрибута: Доступ к геттеру выглядит как чтение обычного атрибута (
obj.name), а не вызов метода (obj.name()). - Атрибут только для чтения: Если определить только
@propertyбез соответствующего@name.setter, атрибут станет read-only, и попытка присвоить ему значение вызоветAttributeError. - Инкапсуляция: Геттеры скрывают внутреннее представление данных (например,
_first_name) от внешнего кода, предоставляя публичный и контролируемый API.
Ответ 18+ 🔞
Ну слушай, вот есть у тебя класс, а в нём какие-то данные, которые ты спрятал подчёркиванием, типа _first_name. И всё бы ничего, но иногда хочется наружу выдать не просто сырые данные, а что-то посчитанное или красиво оформленное. Вот тут и приходит на помощь этот самый @property, ёпта.
Это не просто метод, а такая хитрая жопа, которая прикидывается обычным атрибутом. Ты к нему обращаешься как к полю — user.full_name, а на самом деле срабатывает целая функция, которая может там чего угодно понаделать. Удобно, блядь!
Смотри, зачем это вообще нужно, кроме как для красоты:
- Вычисляемые свойства. Ну вот как раз пример с полным именем. Хранишь отдельно имя и фамилию, а геттер их склеивает и капитализирует. И не надо каждый раз руками это делать.
- Логика при чтении. Можешь перед возвратом данные отформатировать, проверить, подгрузить из базы — хуй с горы, что угодно.
- Только для чтения. Если ты определил только геттер через
@property, а сеттер (@full_name.setter) не сделал — всё, пиши пропало. Попробуй присвоить значение — получишьAttributeErrorв ебало. Отличный способ сделать атрибут неизменяемым снаружи.
Вот смотри на код, тут всё просто:
class User:
def __init__(self, first_name, last_name):
self._first_name = first_name # Спрятали, блядь, под капот
self._last_name = last_name
@property
def full_name(self): # А это наш геттер, маскирующийся под атрибут
"""Возвращает полное имя пользователя."""
return f"{self._first_name} {self._last_name}".title()
# Использование
user = User("john", "doe")
# Смотри, магия! Скобок нет, а работает!
print(user.full_name) # Вывод: John Doe
И главная фишка, блядь — инкапсуляция. Снаружи всем похуй, как ты там внутри имя хранишь: в одном поле, в двух, в базе данных или в облаке. Интерфейс-то один — full_name. Меняй внутреннюю кухню, не ломая внешний код. Красота, ёпта!