我正在编写一个哈希函数来创建一些给定大小的哈希值(例如20位)。
我已经学会了如何以二进制形式将哈希写入文件(请参阅我的相关问题here),但现在我想使用最小内存分配来处理Python(2.7)中的这些哈希。现在它们被输入为int,因此它们每个被分配24个字节,这对于20位对象来说是巨大的。
如何创建任意大小的自定义Python对象(例如在我的情况下为3个字节)?
答案 0 :(得分:1)
你可以通过将每个对象的位打包成一个比特(或布尔)值的打包数组来做你想做的事情。有许多现有的Python bitarray
扩展模块可用。实现更高级别的固定位宽整数值数组"一个是一个相对简单的过程。
这里有一个基于pypi中的一个例子,用C语言实现了速度:
# uses https://pypi.python.org/pypi/bitarray
from bitarray import bitarray as BitArray
class PackedIntArray(object):
""" Packed array of unsigned fixed-bit-width integer values. """
def __init__(self, array_size, item_bit_width, initializer=None):
self.array_size = array_size
self.item_bit_width = item_bit_width
self.bitarray = BitArray(array_size * item_bit_width)
if initializer is not None:
try:
iter(initializer)
except TypeError: # not iterable
self.bitarray.setall(initializer) # set all to bool(initializer)
else:
for i in xrange(array_size):
self[i] = initializer[i] # must be same length as array
def __getitem__(self, index):
offset = index * self.item_bit_width
bits = self.bitarray[offset: offset+self.item_bit_width]
return reduce(lambda x, y: (x << 1) | y, bits, 0)
def __setitem__(self, index, value):
bits = BitArray('{:0{}b}'.format(value, self.item_bit_width))
offset = index * self.item_bit_width
self.bitarray[offset: offset+self.item_bit_width] = bits
def __len__(self):
""" Return the number of items stored in the packed array.. """
return self.array_size
def length(self):
""" Return the number of bits stored in the bitarray.. """
return self.bitarray.length()
def __repr__(self):
return('PackedIntArray({}, {}, ('.format(self.array_size,
self.item_bit_width) +
', '.join((str(self[i]) for i in xrange(self.array_size))) +
'))')
if __name__ == '__main__':
from random import randrange
# hash function configuration
BW = 8, 8, 4 # bit widths of each integer
HW = sum(BW) # total hash bit width
def myhash(a, b, c):
return (((((a & (2**BW[0]-1)) << BW[1]) |
b & (2**BW[1]-1)) << BW[2]) |
c & (2**BW[2]-1))
hashes = PackedIntArray(3, HW)
print 'length of hashes array: {:,} bits'.format(hashes.length())
print ''
print 'populate hashes array:'
for i in xrange(len(hashes)):
hashed = myhash(*(randrange(2**bit_width) for bit_width in BW))
print ' hashes[{}] <- {:,} (0b{:0{}b})'.format(i, hashed, hashed, HW)
hashes[i] = hashed
print ''
print 'contents of hashes array:'
for i in xrange(len(hashes)):
print (' hashes[{}]: {:,} '
'(0b{:0{}b})'.format(i, hashes[i], hashes[i], HW))
输出:
length of hashes array: 60 bits
populate hashes array:
hashes[0] <- 1,017,914 (0b11111000100000111010)
hashes[1] <- 75,689 (0b00010010011110101001)
hashes[2] <- 750,954 (0b10110111010101101010)
contents of hashes array:
hashes[0]: 1,017,914 (0b11111000100000111010)
hashes[1]: 75,689 (0b00010010011110101001)
hashes[2]: 750,954 (0b10110111010101101010)
注意:bitarray.bitarray
个对象也有方法可以在文件中写入和读取它们的位。这些也可用于提供与上述PackedIntArray
类类似的功能。