Bit shifting in Python I am trying to "decode" a file which has every byte shifted its bits.

I have successfully managed to decode this by reading the file, and then byte by byte doing the following (b_int is the integer of the single byte, it will not be 9 bits or 7 bits, always 8 bit):


right shift all bits 1 place b_int &gt;&gt; 1
left shift all bits 7 places b_int &lt;&lt; 7
calculate the lower 8 bits of the left_shifted '{0:08b}'.format(left_shifted)[-8:] (and convert this string back to int with int(binary_8_bits, 2))
do an or on the right_shifted, and lower 8 bits of left_shifted right_shifted | lower_8_left_shifted
from int back to byte bytes([shifted])
write the result to a file


All this is working, but is very slow, as it has to process byte for byte done in the for byte in data loop.

My question: is there a faster way of doing this?

Full program:

def shift_bits(b_int):
    return (b_int &gt;&gt; 1) | (int('{0:08b}'.format(b_int &lt;&lt; 7)[-8:], 2))

def decode_ss(filename):
    with open(filename, 'rb') as openfile:
        data = openfile.read()
    outputfilename = ''.join(filename.split('.')[:-2]) + '.txt'
    with open(outputfilename, 'wb') as output:
        for byte in data:
            output.write(bytes([shift_bits(byte)]))

filename = r'C:\inputfile.txt.ss'
decode_ss(filename)
print('done')
Since b_int is limited to bytes we can change your code a little to remove the formatting.

The left_shift can only have two states, if b_int &amp; 1 is 1 or 0. And so is the same as ((b_int &amp; 1) &lt;&lt; 7). (b_int &gt;&gt; 1) is as simple as it gets, and so this can stay the same.

And so I changed it to:

def shift_bits(b_int):
    return (b_int &gt;&gt; 1) | (int('{0:08b}'.format(b_int &lt;&lt; 7)[-8:], 2))

def p_shift_bits(b_int):
    return ((b_int &amp; 1) &lt;&lt; 7) | (b_int &gt;&gt; 1)


Which works as intended:

for i in range(1 &lt;&lt; 9):
    if shift_bits(i) != p_shift_bits(i):
        print(i)
        break


However, you can still speed it up if you used functools.lru_cache:

@functools.lru_cache(None)
def pc_shift_bits(b_int):
    return ((b_int &amp; 1) &lt;&lt; 7) | (b_int &gt;&gt; 1)




These gave the following timings:

&gt;&gt;&gt; timeit.timeit('shift_bits(i)', 'from __main__ import shift_bits; i=183')
1.9397294419024576
&gt;&gt;&gt; timeit.timeit('p_shift_bits(i)', 'from __main__ import p_shift_bits; i=183')
0.4003988483403518
# Yes heavily biased, but if the length of data is greater than 256, it comes into play.
&gt;&gt;&gt; timeit.timeit('pc_shift_bits(i)', 'from __main__ import pc_shift_bits; i=183')
0.15648568020111497