Автостопом по Python - [46]

Шрифт
Интервал

Дескрипторы и декораторы свойств (используйте неизменяемость, когда это идет на пользу API)

Tablib — наша первая библиотека, в которой используется синтаксис декораторов Python, описанный в подразделе «Декораторы» раздела «Структурируем проект» главы 4. Синтаксисом предусмотрено указывать символ @ перед именем функции, вся конструкция размещается над другой функцией. Декоратор изменяет (или декорирует) функцию, которая находится под ним. В следующем фрагменте кода свойство изменяет функции Dataset.height и Dataset.width, делая их дескрипторами — классами, в которых определен хотя бы один из следующих методов: __get__(), __set__() или __delete__() (геттер, сеттер и метод удаления). Например, поиск атрибута Dataset.height приведет к срабатыванию функции-геттера, сеттера или удаления в зависимости от контекста применения атрибута. Такое поведение присуще только новым классам (их мы вскоре обсудим). Для получения более подробной информации о дескрипторах обратитесь к довольно полезному руководству по Python по адресу https://docs.python.org/3/howto/descriptor.html.



Именно так используется декоратор. В данном случае свойство изменяет Dataset.height, чтобы оно вело себя как свойство, а не как связанный метод. Он может работать только с методами классов.

Когда свойство применяется как декоратор, атрибут height вернет высоту Dataset, но вы не можете задать высоту множества данных, вызвав Dataset.height.

Так выглядят атрибуты height и width при использовании:

>>>> import tablib

>>>> data = tablib.Dataset()

>>>> data.header = ("amount", "ingredient")

>>>> data.append(("2 cubes", "Arcturan Mega-gin"))

>>>> data.width

>2

>>>> data.height

>1

>>>>

>>>> data.height = 3

>Traceback (most recent call last):

>····File "", line 1, in

>AttributeError: can't set attribute

Доступ к data.height можно получить так же, как и к любому другому атрибуту, но изменить его значение вы не можете — оно высчитывается на основе данных и всегда актуально. Такой дизайн API весьма эргономичен: конструкцию data.height проще ввести на клавиатуре, чем data.get_height(); понятно, что означает data.height. Поскольку значение этого свойства выводится на основе данных (значение свойства нельзя задать, для него определена только функция-геттер), можно не переживать, что значение свойства рассинхронизируется с реальными данными.

Декоратор свойства можно применить только к атрибутам классов и только к тем классам, которые наследуют от base object object (например, class MyClass(object), а не class MyClass() — в Python 3 всегда выполняется наследование от объекта).

Один и тот же инструмент используется при создании API для импорта и экспорта данных в Tablib для разных форматов (Tablib не хранит строку для каждого формата). Вместо этого применяются Dataset-атрибуты csv, json и yaml, они похожи на свойства Dataset.height и Dataset.width, показанные в предыдущем примере: вызывают функцию, которая генерирует результат из сохраненных данных или преобразует входной формат и затем заменяет основные данные. Но существует только один набор данных.

Когда свойство data.csv находится с левой стороны знака «равно», вызывается функция-сеттер для этого свойства, которая преобразует dataset из формата CSV. Когда свойство data.yaml находится с правой стороны знака «равно» или стоит отдельно, вызывается функция-геттер для создания строки в заданном формате на основе внутреннего набора данных. Рассмотрим пример.



Свойство data.csv, которое стоит с левой стороны от знака «равно» (оператора присваивания), вызывает функцию formats.csv.import_set(), передавая data в качестве первого аргумента, и строку, содержащую ингредиенты Пангалактического Грызлодера, в качестве второго аргумента.

Свойство data.yaml, стоящее отдельно, вызывает функцию formats.yaml.export_set(), передавая data в качестве аргумента, выводя строку в формате YAML для функции print().

Функции для получения, установки и удаления данных могут быть привязаны к единому атрибуту с помощью property. Его сигнатура выглядит так: property(fget=None, fset=None, fdel=None, doc=None), fget определяет функцию-геттер (formats.csv.import_set()), fset — функцию-сеттер (formats.csv.export_set()), а fdel — функцию удаления данных (оставлена пустой). Далее мы увидим код, в котором программно устанавливаются свойства форматирования.

Форматы файлов, зарегистрированные программно (не повторяйте дома)

Tablib помещает все подпрограммы для форматирования в подпакет formats. Это делает чище основной модуль core.py — и целый пакет становится модульным; добавлять новые форматы файлов будет нетрудно. Несмотря на то что можно копировать фрагменты практически идентичного кода и импортировать поведение при импорте и экспорте для каждого формата отдельно, все форматы программно загружаются в свойства, названные в честь каждого формата, в класс Dataset.

В следующем примере кода мы выводим все содержимое файла formats/__init__.py, поскольку файл не так велик и мы хотим показать, как определяется formats.available.



В этой строке интерпретатору Python явно указывается, что файл имеет кодировку UTF-8


Рекомендуем почитать
Графика DirectX в Delphi

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


Вторая жизнь старых компьютеров

Сейчас во многих школах, институтах и других учебных заведениях можно встретить компьютеры старого парка, уже отслужившие свое как морально, так и физически. На таких компьютерах можно изучать разве что Dos, что далеко от реалий сегодняшнего дня. К тому же у большинства, как правило, жесткий диск уже в нерабочем состоянии. Но и выбросить жалко, а новых никто не дает. Различные спонсоры, меценаты, бывает, подарят компьютер (один) и радуются, как дети. Спасибо, конечно, большое, но проблемы, как вы понимаете, этот компьютер в общем не решает, даже наоборот, усугубляет, работать на старых уже как-то не хочется, теперь просто есть с чем сравнивать.


DirectX 8. Начинаем работу с DirectX Graphics

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


Симуляция частичной специализации

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


Обработка событий в С++

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


Питон — модули, пакеты, классы, экземпляры

Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.


Философия DevOps. Искусство управления IT

IT-принцип «agile» стал мантрой цифровой эпохи. С ростом проектов, переходом от монолитных приложений к системе микросервисов, увеличением и накоплением продуктов возникают вопросы, которые требуют совершенно иного подхода. Теперь наибольший интерес вызывает находящаяся на стыке разработки и операционного управления методология DevOps.DevOps – это не просто набор техник, это философия. Разработчики, зацикленные на пользователях, должны уделять внимание поддержке и ее запросам. Сисадмины должны сообщать о проблемах продукта и вносить свой вклад в улучшение процесса работы.


iOS. Приемы программирования

Книга, которую вы держите в руках, представляет собой новый, полностью переписанный сборник приемов программирования по работе с iOS. Он поможет вам справиться с наболевшими проблемами, с которыми приходится сталкиваться при разработке приложений для iPhone, iPad и iPod Touch. Вы быстро освоите всю информацию, необходимую для начала работы с iOS 7 SDK, в частности познакомитесь с решениями для добавления в ваши приложения реалистичной физики или движений — в этом вам помогут API UIKit Dynamics.Вы изучите новые многочисленные способы хранения и защиты данных, отправки и получения уведомлений, улучшения и анимации графики, управления файлами и каталогами, а также рассмотрите многие другие темы.


Простой Python. Современный стиль программирования

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