I think this does what you want. It uses the referenced bitio
module from another answer of mine to write/read the bits to/from a file.
Operating systems generally require files to be a multiple of 8 bits in size, so this would end up creating a 24-bit (3 byte) file to store a single 20-bit value. This 16.7% of overhead per 20-bit value wouldn't occur, of course, if you wrote several of them, one immediately after the another, and didn't call flush()
until after the last.
import bitio # see https://stackoverflow.com/a/10691412/355230
# hash function configuration
BW = 8, 8, 4 # bit widths of each integer
HW = sum(BW) # total bit width of hash
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))
hashed = myhash(60, 113, 5)
print('{:0{}b}'.format(hashed, HW)) # --> 00111100011100010101
with open('test.bits', 'wb') as outf:
bw = bitio.BitWriter(outf)
bw.writebits(hashed, HW)
bw.flush()
with open('test.bits', 'rb') as inf:
br = bitio.BitReader(inf)
val = br.readbits(HW)
print('{:0{}b}'.format(val, HW)) # --> 00111100011100010101