Travis Griggs
Travis Griggs

Reputation: 22262

Most pythonic way to create bytes() of size N with non-zero initial value?

I could do something like

initialValue = 0x42
width = 113
someBytes = bytes([initialValue] * width)

This wastes time creating an intermediate list just to throw it away though.

or

someBytes = bytearray(width)
for n in range(width):
  someBytes[n] = initialValue

But that's highly un-functional, and starts with an initial value of zero, which will just be immediately replaced, and I need to use a bytearray for the assignment to work.

Is there a more python/simple/terse way to accomplish this?

(python3 btw)

Follow Up:

I ended up using the bytes([initialValue]) * width approach. I think the only thing that is "less than obvious" is the need to use a regular list of short lived state to create a byte array with an initial value, but that's independent of the width allocation, and is consistent with some of the other python collections.

I did do some timing that was interesting. One would expect the stretched bytes to be faster than the bytes created from a stretched list.

>>> timeit("bytes([initial]) * width",
...  "width = 256; initial = 0x42", number=100000)
0.11861954815685749

vs

>>> timeit("bytes([initial] * width)",
...   "width = 256; initial = 0x42", number=100000)
0.5535310138948262

As the size of width goes up, the difference becomes more and more pronounced. Another interesting approach that I tried was using a comprehension for creation. I was surprised it just how slow this was:

>>> timeit("bytes(initial for _ in range(width))",
...   "width = 256; initial = 0x42", number=100000)
2.3924577180296183

As the width went up this one really spread away from the original. Since my initialValue was determined programatically, I was not in a position to use that approach, but its speed is actually quite fast, which surprised me a bit, that the overhead of creating the one element bytes from a list was that significant:

>>> timeit("b'\x42' * width",
...   "width = 256; initial = 0x42", number=100000)
0.010320456698536873

This is fully 10x faster than the otherwise fast, but non-literal solution.

Upvotes: 2

Views: 2360

Answers (1)

BrenBarn
BrenBarn

Reputation: 251478

Just do the multiplication after creating the bytes:

bytes([initialValue])*width

Upvotes: 7

Related Questions