Читаем Автостопом по Python полностью

Скорости Python предпочитает читаемость. Его дизайн, афоризмы, из которых состоит его дзен, и раннее влияние, которое на него оказали языки вроде ABC (http://bit.ly/abc-to-python), — все это заставляет ставить дружелюбие к пользователю над производительностью (более подробно об оптимизации мы поговорим в разделе «Скорость» главы 8).

Использование свойства __slots__ в Tablib — этот тот случай, когда оптимизация имеет значение. Данная ссылка выглядит несколько странно, она доступна только для новых классов (они описаны через несколько страниц), но мы хотим показать, что при необходимости вы можете оптимизировать Python.

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

Рассмотрим фрагмент из документации __slots__ (http://bit.ly/__slots__-doc).

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

Ситуацию можно изменить путем объявления __slots__ в описании класса. Объявление __slots__ принимает последовательность переменных объекта и резервирует достаточный объем памяти для каждой переменной. Место экономится, поскольку для каждой переменной теперь не создается __dict__.

Обычно вам не следует об этом беспокоиться: обратите внимание, что свойство __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__() и __set­sta­te__() и сериализации обратитесь к документации __getstate__ (http://bit.ly/__getstate__-doc).

Примеры из стиля Tablib

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

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

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

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

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

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

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

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

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

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

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

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

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

100 знаменитых харьковчан
100 знаменитых харьковчан

Дмитрий Багалей и Александр Ахиезер, Николай Барабашов и Василий Каразин, Клавдия Шульженко и Ирина Бугримова, Людмила Гурченко и Любовь Малая, Владимир Крайнев и Антон Макаренко… Что объединяет этих людей — столь разных по роду деятельности, живущих в разные годы и в разных городах? Один факт — они так или иначе связаны с Харьковом.Выстраивать героев этой книги по принципу «кто знаменитее» — просто абсурдно. Главное — они любили и любят свой город и прославили его своими делами. Надеемся, что эти сто биографий помогут читателю почувствовать ритм жизни этого города, узнать больше о его истории, просто понять его. Тем более что в книгу вошли и очерки о харьковчанах, имена которых сейчас на слуху у всех горожан, — об Арсене Авакове, Владимире Шумилкине, Александре Фельдмане. Эти люди создают сегодняшнюю историю Харькова.Как знать, возможно, прочитав эту книгу, кто-то испытает чувство гордости за своих знаменитых земляков и посмотрит на Харьков другими глазами.

Владислав Леонидович Карнацевич

Неотсортированное / Энциклопедии / Словари и Энциклопедии