Мне понравилась идея xperroni . Но я думаю, что реализацию можно упростить, используя прямое наследование от ndarray вместо его переноса.
from hashlib import sha1
from numpy import ndarray, uint8, array
class HashableNdarray(ndarray):
def __hash__(self):
if not hasattr(hasattr, '__hash'):
self.__hash = int(sha1(self.view(uint8)).hexdigest(), 16)
return self.__hash
def __eq__(self, other):
if not isinstance(other, HashableNdarray):
return super(HashableNdarray, self).__eq__(other)
return super(HashableNdarray, self).__eq__(super(HashableNdarray, other)).all()
NumPy ndarray
можно рассматривать как производный класс и использовать как хешируемый объект. view(ndarray)
можно использовать для обратного преобразования, но в большинстве случаев оно даже не требуется.
>>> a = array([1,2,3])
>>> b = array([2,3,4])
>>> c = array([1,2,3])
>>> s = set()
>>> s.add(a.view(HashableNdarray))
>>> s.add(b.view(HashableNdarray))
>>> s.add(c.view(HashableNdarray))
>>> print(s)
{HashableNdarray([2, 3, 4]), HashableNdarray([1, 2, 3])}
>>> d = next(iter(s))
>>> print(d == a)
[False False False]
>>> import ctypes
>>> print(d.ctypes.data_as(ctypes.POINTER(ctypes.c_double)))
<__main__.LP_c_double object at 0x7f99f4dbe488>