我正在做一些串行协议的东西,并想在 python 中实现一个基本的字节填充算法。我正在努力确定什么是最 Pythonic 的方法。
字节填充基本上只是用由转义字节和以可逆方式(例如异或)转换的原始字节组成的一对替换任何“保留”字节。
到目前为止,我已经提出了 5 种不同的方法,每种方法都有我不喜欢的地方:
1 过孔发生器
def stuff1(bits):
for byte in bits:
if byte in _EscapeCodes:
yield PacketCode.Escape
yield byte ^ 0xFF
else:
yield byte
这可能是我最喜欢的,但也许只是因为我对基于产量的生成器有点着迷。我担心发电机会使它变慢,但它实际上是第二快的。
2 简单的字节()
def stuff2(bits):
result = bytes()
for byte in bits:
if byte in _EscapeCodes:
result += bytes([PacketCode.Escape, byte ^ 0xFF])
else:
result += bytes([byte])
return result
经常必须创建单个元素数组才能将它们丢弃,因为我不知道任何“带有一个附加元素的复制”操作。它是最慢的。
3 使用字节数组()
def stuff3(bits):
result = bytearray()
for byte in bits:
if byte in _EscapeCodes:
result.append(PacketCode.Escape)
result.append(byte ^ 0xFF)
else:
result.append(byte)
return result
似乎比直接bytes()
方法更好。实际上比产量生成器慢,并且一次可以做一个字节(而不是需要中间的 1 个元素集合)。但是感觉很野蛮。这是包性能的中间。
4 字节IO()
def stuff4(bits):
bio = BytesIO()
for byte in bits:
if byte in _EscapeCodes:
bio.write(bytes([PacketCode.Escape, byte ^ 0xFF]))
else:
bio.write(bytes([byte]))
return bio.getbuffer()
我喜欢这里的基于流的方法。但令人讨厌的是,似乎没有像write1
API 这样可以只添加 1 个字节的东西,所以我必须bytes
再次制作这些中间值。如果有“写单字节”,我想要这个。它连接最慢。
5 使用替换()
def stuff5(bits):
escapeStuffed = bytes(bits).replace(bytes([PacketCode.Escape]), bytes([PacketCode.Escape, PacketCode.Escape ^ 0xFF]))
stopStuffed = escapeStuffed.replace(bytes([PacketCode.Stop]), bytes([PacketCode.Escape, PacketCode.Stop ^ 0xFF]))
return stopStuffed.replace(bytes([PacketCode.Start]), bytes([PacketCode.Escape, PacketCode.Start ^ 0xFF]))
这是最快的。但我不喜欢代码读取和中间扫描的方式。
我还尝试使用translate()
,但 AFAICT,它只能翻译 1:1 序列。