在python中交换字节的有效方法

use*_*125 4 python swap bytearray endianness

我有一些bytearray长度2*n:

a1 a2 b1 b2 c1 c2
Run Code Online (Sandbox Code Playgroud)

我需要在每个2字节字中切换字节字节序,并使:

a2 a1 b2 b1 c2 c1
Run Code Online (Sandbox Code Playgroud)

现在我使用下一个方法但是我的任务非常慢:

converted = bytearray([])
for i in range(int(len(chunk)/2)):
   converted += bytearray([ chunk[i*2+1], chunk[i*2] ])
Run Code Online (Sandbox Code Playgroud)

是否可以bytearray通过调用某些system/libc函数来切换endian ?


好的,多亏了所有,我提出了一些建议:

import timeit

test = [
"""
converted = bytearray([])
for i in range(int(len(chunk)/2)):
   converted += bytearray([ chunk[i*2+1], chunk[i*2] ])
""",
"""
for i in range(0, len(chunk), 2):
    chunk[i], chunk[i+1] = chunk[i+1], chunk[i]
""",
"""
byteswapped = bytearray([0]) * len(chunk)
byteswapped[0::2] = chunk[1::2]
byteswapped[1::2] = chunk[0::2]
""",
"""
chunk[0::2], chunk[1::2] = chunk[1::2], chunk[0::2]
"""
]

for t in test:
    print(timeit.timeit(t, setup='chunk = bytearray([1]*10)'))
Run Code Online (Sandbox Code Playgroud)

结果是:

$ python ti.py
11.6219761372
2.61883187294
3.47194099426
1.66421198845
Run Code Online (Sandbox Code Playgroud)

因此,步进为2的步调切片分配现在是最快的.还要感谢F先生的详细解释,但我还没有尝试过numpy

use*_*ica 6

您可以使用步骤为2的切片分配:

byteswapped = bytearray(len(original))
byteswapped[0::2] = original[1::2]
byteswapped[1::2] = original[0::2]
Run Code Online (Sandbox Code Playgroud)

或者如果你想在现场进行:

original[0::2], original[1::2] = original[1::2], original[0::2]
Run Code Online (Sandbox Code Playgroud)

时间显示大规模切片优于大型数组的Python级循环:

>>> timeit.timeit('''
... for i in range(0, len(chunk), 2):
...     chunk[i], chunk[i+1] = chunk[i+1], chunk[i]''',
... 'chunk=bytearray(1000)')
81.70195105159564
>>>
>>> timeit.timeit('''
... byteswapped = bytearray(len(original))
... byteswapped[0::2] = original[1::2]
... byteswapped[1::2] = original[0::2]''',
... 'original=bytearray(1000)')
2.1136113323948393
>>>
>>> timeit.timeit('chunk[0::2], chunk[1::2] = chunk[1::2], chunk[0::2]', 'chunk=
bytearray(1000)')
1.79349659994989
Run Code Online (Sandbox Code Playgroud)

对于小型数组,切片仍然胜过显式循环,但差别并不大:

>>> timeit.timeit('''
... for i in range(0, len(chunk), 2):
...     chunk[i], chunk[i+1] = chunk[i+1], chunk[i]''',
... 'chunk=bytearray(10)')
1.2503637694328518
>>>
>>> timeit.timeit('''
... byteswapped = bytearray(len(original))
... byteswapped[0::2] = original[1::2]
... byteswapped[1::2] = original[0::2]''',
... 'original=bytearray(10)')
0.8973060929306484
>>>
>>> timeit.timeit('chunk[0::2], chunk[1::2] = chunk[1::2], chunk[0::2]', 'chunk=
bytearray(10)')
0.6282232971918802
Run Code Online (Sandbox Code Playgroud)