我有一些长度为2*n
的bytearray
:
a1 a2 b1 b2 c1 c2
我需要在每个2字节的单词中切换字节endian,并使:
a2 a1 b2 b1 c2 c1
现在我使用了下一种方法,但它对我的任务来说非常缓慢:
converted = bytearray([])
for i in range(int(len(chunk)/2)):
converted += bytearray([ chunk[i*2+1], chunk[i*2] ])
是否可以通过调用某些system/libc函数来切换bytearray
的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)'))
结果是:
$ python ti.py
11.6219761372
2.61883187294
3.47194099426
1.66421198845
所以在速度片分配中,现在2步是最快的。也感谢F先生的详细解释,但我还没有尝试,因为numpy
可以使用slice赋值,步骤为2:
或者如果你想在适当的地方做:
计时显示,对于大型数组,切片的性能大大优于Python级别的循环:
对于小数组,切片仍然优于显式循环,但差别并不大:
如果使用numpy的
frombuffer
函数,则可以构造一个实际共享bytearray
物理内存的numpyndarray
,然后交换操作可以就地执行,而不是在副本中执行。您可以直接在
byt
上执行相同的索引,例如但是,在numpy中使用显式类型获得缓冲数组的句柄通常会让您做更多的事情,特别是使用
bytearray
,它本身非常有限。不过要小心。尽管在Python级别,
bytearray
表示无符号的8位整数值(0-255),但实际的底层C实现在bytearrayobject.h
中使用纯的char
作为字节值(see here for more info)。如果对此使用numpy,则可能需要使用dtype=numpy.ubyte
指定frombuffer
的可选dtype
参数。它印出来了
我在处理一个名为buffersort的小型项目时遇到了其中的一些问题,该项目可以对实现可写缓冲区协议的Python对象执行就地排序,就像
bytearray
那样。如果您对从那里获取Cython源代码感兴趣,那么有一个简单的helper函数
_swap
,它可以让您轻松地完成您想要的任务。不过,对于您的用例来说,这可能是非常过分的。也可以将它们交换到适当的位置并使用原始数组。
相关问题 更多 >
编程相关推荐