Home > other >  Why sum() doesn't work on array of bytes elements in python?
Why sum() doesn't work on array of bytes elements in python?

Time:07-03

This code works perfectly:

b'\x4a'   b'\x20'
b'J '

But this doesn't:

sum([b'\x4a', b'\x20'])
TypeError: unsupported operand type(s) for  : 'int' and 'bytes'

Why? How to concatenate many bytes elements?

CodePudding user response:

You can use join instead:

b''.join([b'\x4a', b'\x20'])

Output:

b'J '

CodePudding user response:

If you actually had no choice but to use sum, this is one way you could do it. This iterates over the bytes, converting them to ints and bit-shifting each one to the next byte. Then it sums all of those ints and coverts the sum back to bytes.

This isn't meant to be the "best" answer. It's the "how to do it with sum" answer. You probably shouldn't use this. It's a little bit clever, because it stores the byte length as it goes, and is therefore never wrong or needing a final equation to determine it (as long as your list is of single bytes).

from typing import Iterable

def sum_concat_bytelist(bl:Iterable, e:str='little') -> bytes:
    return sum(int.from_bytes(b,e)<<((l:=i)<<3) for i,b in enumerate(bl)).to_bytes(l 1,e)

If you wanted to be able to use bytes of any length at each list index, you have to make some modifications. This version eliminates enumerate and manages the i manually.

from typing import Iterable

def sum_concat_bytelist(bl:Iterable, e:str='little') -> bytes:
    i, l = 0, lambda n,i: (((n.bit_length() 7)//8)<<3) i #total current bits forced to multiples of 8
    #                      use last `i`---v v---store next `i`
    return sum((n:=int.from_bytes(b,e))<<(i,i:=l(n,i))[0] for b in bl).to_bytes((i 7)//8,e)
        
print(sum_concat_bytelist([b'\x20\x4a',b'\x4a\x20']))

Both of these ways are probably about as good as it's going to get for what they are, but at best, I would consider this just an experiment. Using .join is the way to go.

  • Related