Обычно вам не следует об этом беспокоиться: обратите внимание, что свойство __slots__ не появляется в классах Dataset или Databook — только в классе Row, но поскольку рядов данных может быть очень много, использование __slots__ выглядит хорошим решением. Класс Row не показан в tablib/__init__.py, поскольку является вспомогательным классом для класса Dataset, для каждой строки создается один объект такого класса.

Рассмотрим, как выглядит определение __slots__ в самом начале определения класса Row:

class Row(object):

····"""Внутренний объект Row. Используется в основном для фильтрации."""

····__slots__ = ['_row', 'tags']

····def __init__(self, row=list(), tags=list()):

········self._row = list(row)

········self.tags = list(tags)

····#

····#… и т. д…

····#

Проблема в том, что больше не существует атрибута __dict__, в котором хранятся объекты класса Row, но функция pickle.dump() (вызывается для сериализации объектов) по умолчанию использует __dict__ для сериализации объектов, если только не определен метод __getstate__(). Аналогично во время десериализации (процесса, который читает сериализованные байты и восстанавливает объект в памяти), если метод __setstate__() не определен, метод pickle.load() загружает данные в атрибут объекта __dict__. Рассмотрим, как это обойти.

class Row(object):

····#

····#… пропускаем другие определения…

····#

····def __getstate__(self):

········slots = dict()

········for slot in self.__slots__:

············attribute = getattr(self, slot)

············slots[slot] = attribute

········return slots

····def __setstate__(self, state):

········for (k, v) in list(state.items()):

············setattr(self, k, v)

Для получения более подробной информации о методах __getstate__() и __setstate__() и сериализации обратитесь к документации __getstate__ (http://bit.ly/__getstate__-doc).

<p>Примеры из стиля Tablib</p>

Мы подготовили лишь один пример использования стиля в Tablib — перегрузка операторов (это позволяет рассмотреть детали модели данных Python). Настройка поведения ваших классов позволит разработчикам, использующим ваш API, писать хороший код.

Перегрузка операторов (красивое лучше, чем уродливое). В этом фрагменте кода приводится перегрузка операторов Python, чтобы выполнять операции для строк или столбцов набора данных. В первом фрагменте кода показывается интерактивное применение квадратных скобок [] как для численных индексов, так и для имен столбцов, а во втором — код, который использует это поведение.

Если вы указываете в квадратных скобках числа, этот оператор вернет строку, которая находится в заданной позиции.

Благодаря этому оператору присваивания с квадратными скобками…

… вместо исходной одной оливки у вас становится две.

Здесь выполняется удаление с помощью вырезки — 2:7 указывает на числа 2, 3, 4, 5, 6, но не 7.

Взгляните, насколько сокращается рецепт после выполнения.

Вы также можете получить доступ к столбцам с помощью имени.

В части кода класса Dataset, которая определяет поведение оператора «квадратные скобки», показывается, как обрабатывать доступ по имени столбца и номеру строки.

Во-первых, проверим, что именно мы ищем — столбец (True, если key является строкой) или строку (True, если key является числом или вырезкой).

Этот код проверяет наличие ключа в self.headers и затем…

…явно вызывает исключение KeyError, поэтому, если вы получаете доступ по имени столбца, поведение будет таким же, как и у словаря. Весь блок if/else необязателен для работы функции — если его опустить, исключение ValueError будет сгенерировано функцией self.headers.index(key) в том случае, если ключа нет в self.headers. Единственным его предназначением является предоставление пользователю библиотеки более информативной ошибки.

Здесь определяется, чем является ключ — числом или вырезкой (вроде 2:7). Если вырезкой, _results будет списком, а не объектом класса Row.

Здесь обрабатывается вырезка. Поскольку строки возвращаются как кортежи, значения представляют собой неизменяемые копии реальных данных — и данные из набора (которые хранятся в списках) не будут случайно повреждены в результате присваивания.

Перейти на страницу:

Все книги серии Бестселлеры O'Reilly

Похожие книги