6

我正在做一些串行协议的东西,并想在 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()

我喜欢这里的基于流的方法。但令人讨厌的是,似乎没有像write1API 这样可以只添加 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 序列。

4

0 回答 0