如何解决如何在 Python 中有效地从大块中提取带有偏移量的字节?
block = b'0123456789AB'
我想从每个 4 个字节的块中提取每个 3 个字节的序列并将它们连接在一起。上面块的结果应该是:
b'01245689A' # 3,7 and B are missed
我可以用这样的脚本解决这个问题:
block = b'0123456789AB'
result = b''
for i in range(0,len(block),4):
result += block[i:i + 3]
print(result)
但众所周知,Python 在使用这种 for 循环和字节连接时效率非常低,因此如果我将它应用于一个非常大的字节块,我的方法将永远不会结束。那么有没有更快的执行方式?
解决方法
使其可变并删除不需要的切片?
>>> tmp = bytearray(block)
>>> del tmp[3::4]
>>> bytes(tmp)
b'01245689A'
如果您的块很大并且您想删除几乎所有字节,那么收集您想要的内容可能会更快,类似于您的。虽然您的可能需要二次时间,但最好使用 join
:
>>> b''.join([block[i : i+3] for i in range(0,len(block),4)])
b'01245689A'
(顺便说一句,根据 PEP 8,它应该是 block[i : i+3]
,而不是 block[i:i + 3]
,并且有充分的理由。)
虽然这会构建很多对象,但这可能是内存问题。对于您陈述的案例,它比您的快得多,但比我的 bytearray
慢得多。
使用 block = b'0123456789AB' * 100_000
进行基准测试(远小于您在下面评论中提到的 1GB):
0.00 ms 0.00 ms 0.00 ms baseline
15267.60 ms 14724.33 ms 14712.70 ms original
2.46 ms 2.46 ms 3.45 ms Kelly_Bundy_bytearray
83.66 ms 85.27 ms 122.88 ms Kelly_Bundy_join
基准代码:
import timeit
def baseline(block):
pass
def original(block):
result = b''
for i in range(0,4):
result += block[i:i + 3]
return result
def Kelly_Bundy_bytearray(block):
tmp = bytearray(block)
del tmp[3::4]
return bytes(tmp)
def Kelly_Bundy_join(block):
return b''.join([block[i : i+3] for i in range(0,4)])
funcs = [
baseline,original,Kelly_Bundy_bytearray,Kelly_Bundy_join,]
block = b'0123456789AB' * 100_000
args = block,number = 10**0
expect = original(*args)
for func in funcs:
print(func(*args) == expect,func.__name__)
print()
tss = [[] for _ in funcs]
for _ in range(3):
for func,ts in zip(funcs,tss):
t = min(timeit.repeat(lambda: func(*args),number=number)) / number
ts.append(t)
print(*('%8.2f ms ' % (1e3 * t) for t in ts),func.__name__)
print()
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。