Вопрос
ZODB предоставляет PersistentList
и PersistentMapping
, но мне бы хотелось PersistentSet
.Я написал быстрый урок, который отражает древний PersistentList
из ЗОДБ 2.Потому что нет UserSet
в Python мне пришлось расширить встроенную систему на языке C. set
.
class PersistentSet(UserSet, Persistent):
def __iand__(self, other):
set.__iand__(other)
self._p_changed = 1
...
...
...
def symmetric_difference_update(self, other):
set.symmetric_difference_update(other)
self._p_changed = 1
Код создал «несколько баз имеют конфликт макета экземпляра». ошибка.Я попробовал создать UserSet
обертка вокруг set
, но это тоже не решило проблему.
class UserSet(set):
def __init__(self):
self.value = set
def __getattribute__(self, name):
return self.value.__getattribute__(name
Наконец, я импортировал sets.Set
(заменен встроенным set
), но, похоже, это реализовано и в C.Я не нашел никаких готовых реализаций в PyPI, поэтому сейчас я в тупике.
Какие у меня есть варианты? Возможно, мне придется реализовать набор с нуля или использовать UserDict
и выбросить все value
с.
Решение
Почему бы вам не использовать класс постоянного набора, поставляемый с БТри библиотеки в ZODB.Всего доступно 4 таких класса.IITreeSet и IOTreeSet управляют наборами целых чисел, а OITreeSet и OOTreeSet управляют набором произвольных объектов.Они соответствуют четырем классам BTree: IIBTree, IOBTree, OIBTree и OOBTree соответственно.Их преимущества перед реализацией set, встроенной в Python, заключаются в механизме быстрого поиска (благодаря базовому BTree) и поддержке персистентности.
Вот пример кода:
>>> from BTrees.IIBTree import IITreeSet, union, intersection
>>> a = IITreeSet([1,2,3])
>>> a
<BTrees._IIBTree.IITreeSet object at 0x00B3FF18>
>>> b = IITreeSet([4,3,2])
>>> list(a)
[1, 2, 3]
>>> list(b)
[2, 3, 4]
>>> union(a,b)
IISet([1, 2, 3, 4])
>>> intersection(a,b)
IISet([2, 3])
Другие советы
Перенаправить все запросы атрибутов во внутренний набор:
class PersistentSet(Persistent):
def __init__(self):
self.inner_set = set()
def __getattribute__(self, name):
try:
inner_set = Persistent.__getattribute__(self, "inner_set")
output = getattr(inner_set, name)
except AttributeError:
output = Persistent.__getattribute__(self, name)
return output
Для будущих чтений я просто хотел предложить небольшое улучшение по сравнению с уже предложенными ответами...
Пользовательский класс постоянного набора
class PersistentSet(Persistent):
def __init__(self, *args, **kwargs):
self._set = set(*args, **kwargs)
def __getattr__(self, name):
return getattr(self._set, name)
Постоянный набор классов из библиотеки
from BTrees.OOBTree import OOSet
Смотрите также