Программа курса:
Использование декоратора property
Введение в декораторы
Декораторы в Python — это функции, которые позволяют модифицировать поведение других функций или методов. Они используются для добавления функциональности к существующим методам или атрибутам без изменения их кода. Один из наиболее распространенных случаев использования декораторов — это создание свойств (properties) с помощью декоратора property
.
Декоратор property
позволяет управлять доступом к атрибутам объекта, создавая геттеры и сеттеры, которые обеспечивают контроль над их значениями. Это особенно полезно для инкапсуляции данных и управления доступом к ним.
Создание класса с использованием property
Давайте рассмотрим, как работает декоратор property
на примере простого класса Circle
, который представляет круг. Этот класс будет иметь радиус и позволит вычислять площадь круга.
class Circle:
def __init__(self, radius):
self._radius = radius # Приватный атрибут для хранения радиуса
@property
def radius(self):
"""Геттер для атрибута radius."""
return self._radius
@radius.setter
def radius(self, value):
"""Сеттер для атрибута radius."""
if value <= 0:
raise ValueError("Radius must be positive!")
self._radius = value
@property
def area(self):
"""Свойство для вычисления площади круга."""
return 3.14159 * (self._radius ** 2)
Объяснение примера 1
- Конструктор
__init__
: Мы инициализируем атрибут_radius
, который хранит значение радиуса. Он приватный (начинается с_
), что сигнализирует о том, что он не предназначен для прямого доступа извне класса. - Геттер
radius
: Декоратор@property
позволяет нам определить метод, который будет вызываться при обращении к свойствуradius
. Этот метод возвращает текущее значение_radius
. - Сеттер
radius
: Декоратор@radius.setter
определяет метод, который вызывается при установке нового значения дляradius
. Здесь мы проверяем, является ли новое значение положительным, и выбрасываем исключениеValueError
, если нет. - Свойство
area
: Мы определяем свойствоarea
, которое вычисляет площадь круга на основе радиуса. Оно не имеет сеттера, так как площадь зависит только от радиуса.
Создание объекта и использование класса Circle
Теперь создадим объект класса Circle
и протестируем его методы.
circle = Circle(5)
print("Radius:", circle.radius) # Получаем радиус
print("Area:", circle.area) # Получаем площадь
circle.radius = 10 # Устанавливаем новый радиус
print("New Radius:", circle.radius) # Получаем новый радиус
print("New Area:", circle.area) # Получаем новую площадь
Вывод:
Radius: 5
Area: 78.53975
New Radius: 10
New Area: 314.159
Объяснение вывода
- Вначале мы создаем круг с радиусом 5 и выводим его радиус и площадь. Площадь вычисляется по формуле π * r².
- Затем мы изменяем радиус на 10 и снова выводим радиус и площадь. Как видно, площадь увеличилась, поскольку она зависит от квадрата радиуса.
Обработка ошибок с использованием property
Теперь давайте добавим логику обработки ошибок при установке значений с помощью декоратора property
. Мы уже видели, как выбрасывается ValueError
, если радиус не положительный. Давайте добавим в наш пример дополнительную логику.
class Circle:
def __init__(self, radius):
self._radius = radius
@property
def radius(self):
return self._radius
@radius.setter
def radius(self, value):
if not isinstance(value, (int, float)):
raise TypeError("Radius must be a number!")
if value <= 0:
raise ValueError("Radius must be positive!")
self._radius = value
@property
def area(self):
return 3.14159 * (self._radius ** 2)
Создание объекта и тестирование обработки ошибок
Теперь протестируем новую логику обработки ошибок.
try:
circle = Circle(5)
print("Radius:", circle.radius) # Получаем радиус
circle.radius = -3 # Пытаемся установить отрицательный радиус
except ValueError as e:
print(e) # Выводим сообщение об ошибке
try:
circle.radius = "ten" # Пытаемся установить строку вместо числа
except TypeError as e:
print(e) # Выводим сообщение об ошибке
Вывод:
Radius: 5
Radius must be positive!
Radius must be a number!
Объяснение вывода
- При попытке установить отрицательный радиус, метод-сеттер выбрасывает
ValueError
, и мы обрабатываем это исключение, выводя соответствующее сообщение. - При попытке установить строку вместо числа мы получаем
TypeError
, и также обрабатываем это исключение.
Сложные свойства с логикой
Давайте создадим более сложный пример, где свойство будет иметь логику, связанную с несколькими атрибутами. Мы создадим класс Rectangle
, который будет иметь ширину и высоту, а также свойство для вычисления периметра.
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):
if value <= 0:
raise ValueError("Width must be positive!")
self._width = value
@property
def height(self):
return self._height
@height.setter
def height(self, value):
if value <= 0:
raise ValueError("Height must be positive!")
self._height = value
@property
def perimeter(self):
return 2 * (self._width + self._height)
Создание объекта и использование класса Rectangle
Теперь создадим объект класса Rectangle
и протестируем его свойства.
rectangle = Rectangle(5, 10)
print("Width:", rectangle.width) # Получаем ширину
print("Height:", rectangle.height) # Получаем высоту
print("Perimeter:", rectangle.perimeter) # Получаем периметр
rectangle.width = 7 # Устанавливаем новую ширину
rectangle.height = 12 # Устанавливаем новую высоту
print("New Width:", rectangle.width) # Получаем новую ширину
print("New Height:", rectangle.height) # Получаем новую высоту
print("New Perimeter:", rectangle.perimeter) # Получаем новый периметр
Вывод:
Width: 5
Height: 10
Perimeter: 30
New Width: 7
New Height: 12
New Perimeter: 38
Объяснение вывода
- Мы создаем прямоугольник с шириной 5 и высотой 10, а затем вычисляем его периметр. Изменяя ширину и высоту, мы получаем обновленные значения и периметр.
Свойства и их связь с другими атрибутами
Теперь давайте рассмотрим, как использовать свойства для вычисления значений на основе других атрибутов. Мы создадим класс Person
, у которого будет полное имя и свойство для получения его инициалов.
class Person:
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
@property
def initials(self):
return f"{self.first_name[0].upper()}.{self.last_name[0].upper()}."
.jpg)
Создание объекта и использование класса Person
Теперь создадим объект класса Person
и протестируем его свойства.
person = Person("John", "Doe")
print("Full Name:", f"{person.first_name} {person.last_name}") # Полное имя
print("Initials:", person.initials) # Инициалы
Вывод:
Full Name: John Doe
Initials: J.D.
Объяснение вывода
- Мы создаем объект
Person
с именем "John" и фамилией "Doe". Затем, используя свойствоinitials
, мы получаем инициалы, которые формируются из первых букв имени и фамилии.
Таблица по декораторам property
без примеров:
Пункт | Описание |
---|---|
Что такое декоратор property | Декоратор property позволяет управлять доступом к атрибутам класса, создавая свойства (геттеры и сеттеры). |
Основное назначение | Инкапсуляция логики доступа к атрибутам, добавление контроля над их значениями. |
Синтаксис | Используется синтаксис @property для определения геттера и @имя_свойства.setter для сеттера. |
Геттер | Метод, который возвращает значение атрибута, предоставляя доступ к атрибуту через свойство. |
Сеттер | Метод, который устанавливает значение атрибута, обеспечивая контроль над присваиваемым значением. |
Вычисляемые свойства | Свойства, которые вычисляются на основе других атрибутов, позволяя возвращать значения без хранения их в отдельной переменной. |
Обработка ошибок | Возможность проверки условий (например, положительное значение) в методах-сеттерах. |
Связь с другими атрибутами | Свойства могут зависеть от значений других атрибутов, позволяя реализовать взаимосвязи между ними. |
Преимущества использования | Улучшение структуры кода, возможность добавления логики доступа к атрибутам без изменения их интерфейса. |
Декоратор property
в Python — мощный инструмент, позволяющий управлять доступом к атрибутам класса и инкапсулировать логику, связанную с ними. Мы рассмотрели несколько примеров использования декоратора property
, включая геттеры, сеттеры и вычисляемые свойства. Теперь вы можете использовать декоратор property
в своих проектах, чтобы улучшить структуру и читаемость кода. Если у вас есть дополнительные вопросы или вы хотите рассмотреть более сложные примеры, не стесняйтесь спрашивать!
Комментарии
Ограниченный доступ
Вы можете только просматривать лекции, так как данный курс является платным. Чтобы получить полный доступ к курсу, приобретите его!