2015-04-19 2 views
1

Каков наилучший способ создания набора объектов, похожих на bitarray, чтобы я мог эффективно тестировать членство. Наивный способ, кажется, не работает, как я ожидал:Python bitarray set

>>> from bitarray import bitarray 
>>> 
>>> bitarray_set = set([bitarray('0000'), bitarray('0001')]) 
>>> bitarray_set 
set([bitarray('0001'), bitarray('0000')]) 
>>> 
>>> bitarray('0000') in bitarray_set 
False 

Обходной должен держать отдельный набор строк или другой более дружественный объект в качестве ключей. Затем преобразуйте bitarray в строку и проверьте членство в этом наборе. Но это кажется немного громоздким. Есть ли лучшее решение?

ответ

5

Оказывается, что bitarray не поддерживает хэш-инвариант:

>>> x = bitarray(b'0000') 
>>> y = bitarray(b'0000') 
>>> x == y 
True 
>>> hash(x) == hash(y) 
False 

Это является нарушением API для __hash__ как documented:

Единственное обязательное свойство является то, что объекты, которые сравнивают равные, имеют одинаковое значение хеша

Это означает, что битрейты являются эффектами нестабильно и не работает надежно в наборах или в словарных словах.

Я рассматривал бы это как ошибку в библиотеке bitarray. Раньше я никогда не слышал о bitarray, и у него, похоже, не много документации. Насколько я вижу, он даже не говорит о том, как должно быть определено равенство для битрейпов, и не предполагается ли их хеширование, но, похоже, оно реализует равенство и хэширование несовместимыми способами.

+1

Я думаю, что вы правы в этой проблеме, но поскольку массивы изменчивы, возможно, они не предназначены для хэширования, и мы должны иметь 'bitarray .__ hash__ = None', чтобы предотвратить это. – DSM

+0

@ DSM: Да, это имело бы смысл. Как я уже сказал, из документации неясно, каково должно быть поведение. Но они либо должны стать неизменными, либо неумелыми. – BrenBarn