Python. Свойства

Перевод статьи Python @property.

Python поддерживает концепцию свойств упрощающих объектно ориентированное программирование. Прежде чем погрузится глубже в детали свойств, рассмотрим зачем могут быть нужны свойства.

Начальный пример

Представим что вы решили сделать класс хранящий температуру в градусах Цельсия. Он также должен реализовывать метод для конвертации температуры в градусы Фаренгейта. Реазуем класс так:

Затем создаём объект этого класса и меняем значение температуры как пожелаем:

Дополнительные десятичные разряды при конвертации в градусы Фаренгейта происходят из-за арифметической ошибки с плавающей запятой (попробуйте сложить 1.1 + 2.2 в интерпретаторе).

Когда мы присваиваем или извлекаем атрибут объекта, такой как temperature, Python ищет его в словаре объекта __dict__.

Внутри интерпретатора man.temperature становится man.__dict__['temperature'].

Теперь представим что наш класс стал популярным, много клиентов стали использовать его в своих программах. Однажды, важный клиент пришёл в нам и сообщил что температура не может быть ниже -273 градусов Цельсия. Затем он попросил реализовать это ограничение значения. Прислушавшись к этому предложению мы реализуем его и выпускаем новую версию нашего класса.

Использование геттеров и сеттеров

Очевидным решением будет скрыть атрибут temperature (сделать его приватным) и определить интерфейс в виде геттера и сеттера для управления полем.

Добавлены методы get_temperature() и set_temperature(), имя поле temperature заменено на _temperature. Подчёркивание в начале имени используется для обозначения приватных переменных в Python.

Изменения успешно реализуют новые ограничения. Мы больше не можем установить температуру ниже -273.

В языке Python нет приватных переменных. Существуют нормы которым придерживаются разработчики, но язык сам не применяет ограничения.

Но это не является большой проблемой. Гораздо хуже то что все клиенты использующие предыдущую версию класса должны изменить свой код с obj.temperature на obj.get_temperature() и все присвоения obj.temperature = val на obj.set_temperature(val). Наше обновление не поддерживает обратную совместимость. Свойства помогают решить эту проблему.

Свойства

Добавление ограничений в класс в стиле Python:

Мы добавили функции print() внутрь get_temperature() и set_temperature() чтобы ясно видеть когда они запускаются.

Последняя строка кода создаёт объект свойства temperature. Свойство присоединяет некоторый код (get_temperature и set_temperature) к атрибутту класса (temperature).

Код извлекающий значение из temperature автоматически вызывает get_temperature() вместо поиска по словарю (__dict__). Таким же образом, код присваивающий значение temperature автоматически вызовет set_temperature().

После создания объекта появляется сообщение из метода set_temperature(). Это происходит потому что при создании объекта вызывается метод __init__(), а в нём приходит присвоение self.temperature = temperature. Присвоение автоматически вызывает set_temperature().

Любой запрос к полю, такой как c.temperature автоматически вызывает get_temperature(). Ещё несколько примеров:

При использовании свойств мы изменяем класс и реализуем ограничения значения без изменений в клиентском коде. Наша реализация обладает обратной совместимостью.

Обратите внимание, что значение температуры хранится в приватной переменной _temperature. Атрибут temperature является объектом свойства который предоставляет интерфейс доступа к этой приватной переменной.

Глубокое погружение в свойства

В Python, property() это встроенная функция с сигнатурой

  • fget - функция для получения значения атрибута
  • fset - функция для установки значения атрибута
  • fdel - функция для удаления атрибута
  • doc - строка с комментарием

Все аргументы не обязательны, объект свойства может быть создан так:

Объект свойства имеет три метода: getter(), setter() и deleter() для указания fget, fset и fdel после создания объекта. Это означает что строка

эквивалентна коду

Используя декоратор мы можем избежать создания лишних имён get_temperature и set_temperature.

Использования декоратора простой и рекомендуемый способ создания свойств.

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *