← Назад к вопросам

Как использовать метод property?

1.7 Middle🔥 201 комментариев
#Soft Skills

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Использование метода property в Python

Метод @property — это встроенный декоратор Python, который позволяет преобразовать метод класса в атрибут, обеспечивая контроль над доступом к данным без изменения синтаксиса вызова. Это ключевая техника инкапсуляции в Python.

1. Базовый синтаксис

Перепишем простой getter в property:

class Person:
    def __init__(self, name):
        self._name = name  # приватный атрибут (соглашение)
    
    # Без property
    def get_name(self):
        return self._name

# Использование: person.get_name()

# С использованием property
class Person:
    def __init__(self, name):
        self._name = name
    
    @property
    def name(self):
        return self._name

# Использование: person.name (как атрибут, без скобок)
person = Person("Alice")
print(person.name)  # Alice

2. Сеттер (setter)

Property может иметь сеттер для изменения значения с валидацией:

class Person:
    def __init__(self, name, age):
        self._name = name
        self._age = age
    
    @property
    def age(self):
        return self._age
    
    @age.setter
    def age(self, value):
        if value < 0:
            raise ValueError("Возраст не может быть отрицательным")
        self._age = value

person = Person("Bob", 25)
print(person.age)  # 25
person.age = 30    # OK
person.age = -5    # ValueError

3. Делетер (deleter)

Можно также определить поведение при удалении атрибута:

class Person:
    def __init__(self, name):
        self._name = name
    
    @property
    def name(self):
        return self._name
    
    @name.setter
    def name(self, value):
        if not value:
            raise ValueError("Имя не может быть пустым")
        self._name = value
    
    @name.deleter
    def name(self):
        print(f"Удаляем имя {self._name}")
        self._name = None

person = Person("Alice")
del person.name  # Удаляем имя Alice
print(person.name)  # None

4. Вычисляемые свойства

Property полезно для вычисляемых атрибутов:

class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height
    
    @property
    def area(self):
        """Площадь вычисляется динамически"""
        return self.width * self.height
    
    @property
    def perimeter(self):
        return 2 * (self.width + self.height)

rect = Rectangle(5, 10)
print(rect.area)       # 50 (не метод, а свойство)
print(rect.perimeter)  # 30

5. Кэширование с @property

Часто используется для кэширования дорогостоящих вычислений:

class DataProcessor:
    def __init__(self, data):
        self.data = data
        self._cached_result = None
    
    @property
    def processed_data(self):
        if self._cached_result is None:
            # Дорогостоящее вычисление
            self._cached_result = sum(x * 2 for x in self.data)
        return self._cached_result

processor = DataProcessor([1, 2, 3, 4, 5])
print(processor.processed_data)  # 30 (вычисляется один раз)
print(processor.processed_data)  # 30 (из кэша)

6. Property в наследовании

Property корректно работают с наследованием:

class Animal:
    def __init__(self, name):
        self._name = name
    
    @property
    def name(self):
        return self._name

class Dog(Animal):
    @property
    def name(self):
        # Переопределяем property
        return f"Dog: {self._name}"

dog = Dog("Rex")
print(dog.name)  # Dog: Rex

7. Property vs явные методы

Когда использовать что:

# ✅ Используй property если:
# - Это простое получение/установка значения
# - Нужна валидация при присваивании
# - Это вычисляемый атрибут

class User:
    @property
    def email(self):
        return self._email

# ✅ Используй методы если:
# - Операция требует параметров
# - Это дорогостоящая операция
# - Это сложная бизнес-логика

class User:
    def validate_email(self, email):
        return "@" in email
    
    def send_email(self, subject, body):
        # сложная логика отправки
        pass

8. Практический пример с валидацией

class BankAccount:
    def __init__(self, owner, balance=0):
        self.owner = owner
        self._balance = balance
    
    @property
    def balance(self):
        return self._balance
    
    @balance.setter
    def balance(self, value):
        if value < 0:
            raise ValueError("Баланс не может быть отрицательным")
        self._balance = value
    
    def deposit(self, amount):
        if amount <= 0:
            raise ValueError("Сумма должна быть положительной")
        self.balance += amount
    
    def withdraw(self, amount):
        if amount > self._balance:
            raise ValueError("Недостаточно средств")
        self.balance -= amount

account = BankAccount("John", 1000)
print(account.balance)  # 1000
account.deposit(500)    # 1500
account.withdraw(200)   # 1300

Ключевые преимущества

Инкапсуляция — контроль доступа к данным ✅ Валидация — проверка значений при установке ✅ Гибкость — легко добавить логику позже ✅ Удобство — синтаксис атрибута без скобок ✅ Совместимость — не нужно менять вызывающий код

Property — важный инструмент для написания чистого и безопасного кода на Python.

Как использовать метод property? | PrepBro