Как в Python создать setter для атрибута класса

Ответ

В Python сеттер (метод для установки значения) создается с помощью декоратора @<имя_свойства>.setter. Он всегда используется в паре с геттером, который был объявлен через @property.

Основное назначение сеттера — добавление логики (например, валидации) при попытке присвоить новое значение атрибуту.

Пример:

class Circle:
    def __init__(self, radius):
        self._radius = radius  # Внутренний атрибут

    @property
    def radius(self):
        """Getter для радиуса."""
        return self._radius

    @radius.setter
    def radius(self, value):
        """Setter с валидацией для радиуса."""
        if not isinstance(value, (int, float)) or value <= 0:
            raise ValueError("Радиус должен быть положительным числом")
        print(f"Setter called: new radius is {value}")
        self._radius = value

# Использование
circle = Circle(5)

# Присваивание значения вызывает setter
circle.radius = 10 
# Вывод: Setter called: new radius is 10

print(circle.radius) # Вызывает getter
# Вывод: 10

try:
    circle.radius = -2 # Попытка присвоить некорректное значение
except ValueError as e:
    print(e)
    # Вывод: Радиус должен быть положительным числом

Ключевые моменты:

  1. Связь с геттером: Сеттер должен иметь то же имя, что и метод-геттер (radius), а его декоратор формируется из этого имени: @radius.setter.
  2. Автоматический вызов: Сеттер вызывается автоматически при выполнении операции присваивания: circle.radius = 10.
  3. Контроль данных: Это мощный инструмент для обеспечения целостности данных объекта, позволяющий отклонять некорректные значения.

Ответ 18+ 🔞

А, вот смотри, смотри, это же про эти ваши декораторы, да? Ну, которые в Питоне, блядь. Ну, типа, чтобы не просто так переменную менять, а с прибамбасами, с проверками, блядь.

Так вот, есть у тебя свойство, которое ты через @property обозвал, чтобы красиво читалось. А чтобы в него ещё и писать можно было с умом — нужен сеттер, ёпта! И делается он через @<имя>.setter. Главное, чтобы имя совпадало с геттером, а то нихуя не сработает.

Смысл-то в чём? А в том, что ты не просто circle.radius = -5 пишешь, а у тебя там, блядь, целая проверочка влетает: а число ли это? А положительное ли? А не хуйню ли ты мне подсунул? И если хуйню — сразу ошибку в ебало, и всё, никуда не присвоилось, порядок!

Смотри, как это выглядит, на примере круга, блядь:

class Circle:
    def __init__(self, radius):
        self._radius = radius  # Вот эта штука внутри, приватная, блядь

    @property
    def radius(self):
        """Getter для радиуса."""
        return self._radius

    @radius.setter
    def radius(self, value):
        """Setter с валидацией для радиуса."""
        if not isinstance(value, (int, float)) or value <= 0:
            raise ValueError("Радиус должен быть положительным числом")
        print(f"Setter called: new radius is {value}")
        self._radius = value

# Использование
circle = Circle(5)

# Присваивание значения вызывает setter
circle.radius = 10 
# Вывод: Setter called: new radius is 10

print(circle.radius) # Вызывает getter
# Вывод: 10

try:
    circle.radius = -2 # Попытка присвоить некорректное значение
except ValueError as e:
    print(e)
    # Вывод: Радиус должен быть положительным числом

Видишь? Как только пишешь circle.radius = 10 — хоп, и летит твой сеттер работать. Он там проверяет, всё ли гуд, и если да — меняет внутреннюю переменную _radius. А если попробуешь минус два впихнуть — получишь ValueError прямо в лоб, и ничего не изменится, хитрая жопа!

Короче, сеттер — это как охранник у входа в клуб, блядь. Без него любой мудак с улицы зайдёт, а с ним — только по паспорту и в приличном виде. Удобная хуйня, если нужно данные контролировать, а не как попало их менять.