Для чего нужны геттеры в Python и как их создать?

Ответ

В 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, а на самом деле срабатывает целая функция, которая может там чего угодно понаделать. Удобно, блядь!

Смотри, зачем это вообще нужно, кроме как для красоты:

  1. Вычисляемые свойства. Ну вот как раз пример с полным именем. Хранишь отдельно имя и фамилию, а геттер их склеивает и капитализирует. И не надо каждый раз руками это делать.
  2. Логика при чтении. Можешь перед возвратом данные отформатировать, проверить, подгрузить из базы — хуй с горы, что угодно.
  3. Только для чтения. Если ты определил только геттер через @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. Меняй внутреннюю кухню, не ломая внешний код. Красота, ёпта!