Практические примеры использования
Валидация и преобразование данных
class Employee:
def __init__(self, salary):
self._salary = salary
@property
def salary(self):
return self._salary
@salary.setter
def salary(self, value):
if not isinstance(value, (int, float)):
raise TypeError("Salary must be a number")
if value < 0:
raise ValueError("Salary cannot be negative")
self._salary = round(value, 2)
Ленивая загрузка и кэширование
class DatabaseConnection:
def __init__(self, connection_string):
self._connection_string = connection_string
self._connection = None
@property
def connection(self):
if self._connection is None:
self._connection = self._establish_connection()
return self._connection
def _establish_connection(self):
## Simulate expensive connection process
return f"Connected to {self._connection_string}"
Только для чтения атрибуты
class ImmutableConfig:
def __init__(self, config_dict):
self._config = config_dict
@property
def database_host(self):
return self._config.get('database_host')
@property
def database_port(self):
return self._config.get('database_port')
Сценарии использования
Сценарий |
Преимущество свойства |
Пример |
Валидация входных данных |
Предотвращение недействительных данных |
Проверка возраста |
Вычисляемые значения |
Динамические вычисления |
Площадь геометрических фигур |
Контроль доступа |
Ограничение прямых изменений |
Защита конфиденциальных данных |
Логирование и мониторинг
class SensorData:
def __init__(self):
self._temperature = 0
@property
def temperature(self):
return self._temperature
@temperature.setter
def temperature(self, value):
print(f"Temperature changed: {self._temperature} -> {value}")
self._temperature = value
Управление зависимостями свойств
class Rectangle:
def __init__(self, width, height):
self._width = width
self._height = height
@property
def width(self):
return self._width
@width.setter
def width(self, value):
self._width = value
## Trigger potential recalculations
self._update_derived_properties()
@property
def area(self):
return self._width * self._height
def _update_derived_properties(self):
## Additional logic for dependent properties
pass
Рабочий процесс создания свойства
graph TD
A[Определить потребность в атрибуте] --> B{Требуется ли пользовательская логика?}
B -->|Да| C[Определить методы свойства]
B -->|Нет| D[Использовать стандартный атрибут]
C --> E[Реализовать геттер/сеттер]
E --> F[Добавить валидацию/преобразование]
Рекомендация LabEx
В LabEx мы подчеркиваем использование динамических свойств для создания более интеллектуальных и самоконтролируемых классов, которые инкапсулируют сложную логику, сохраняя при этом чистый и читаемый код.
Продвинутое композирование
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}"
@full_name.setter
def full_name(self, name):
self._first_name, self._last_name = name.split(' ', 1)