首页 > 解决方案 > python:检查字节对象中前导零的有效方法

问题描述

我正在寻找一种有效的方法来检查字节对象中的前导零。检查也应该针对半食进行。现在我只用search_zeros函数检查字节;其中输入参数是::n要检查的前导零的数量,以及inp_bytes字节对象:

def search_zeros(inp_bytes, n): # inp_bytes is always 20 bytes
    if n % 2 ==0:
        bytes_to_check = n // 2
        check_bytes = bytes(bytes_to_check)
    else:
        # check for nibbles?
        return
    if inp_bytes[:bytes_to_check] == check_bytes:
        return inp_bytes 

print(search_zeros(b'\x00\x002\xe04\x83\xb1.)\x1c\x17\xa5\xb7u\xcc\n\xb0\xfdg0', 2))
>>>b'\x00\x002\xe04\x83\xb1.)\x1c\x17\xa5\xb7u\xcc\n\xb0\xfdg0'

# How to check for nibbles?
print(search_zeros(b'\x00\xe04\xe04\x83\xb1.)\x1c\x17\xa5\xb7u\xcc\n\xb0\xfdg0', 1))
>>> None
  

我正在阅读有关按位运算的内容,并且正在尝试熟悉该主题。这可以在这里适用吗?

编辑

我知道我可以使用.startswith(b'\x00'),但有更快的方法吗?

澄清:

inp_bytes如果函数以恰好零个半字节开始,则该函数应该返回n,不多不少,否则它应该返回None

标签: pythonpython-3.x

解决方案


我会避免构造check_bytes,因为当 n 非常大时,这会消耗内存中不必要的存储空间。所以我的方法是使用循环或等效的理解。

其他注意事项:

  • 如果字符串太短,我假设您不希望出现异常,因此我为这种情况添加了一些逻辑。我认为len(inp_bytes)是一个恒定的时间操作,所以这应该很快。
  • 我使用的事实是一个字节y在非零时为“真”,我很确定这是一种最快的方式,但基准测试可以确认,如果你真的在所有可以节省的纳秒之后。
  • n如果是奇数,您可以使用按位运算来测试最后一个半字节。请注意,在 Python 中,按位运算是在字节上定义的,而不是在字节序列中定义的。b'\xf0'是一个字节序列,因此会& b'\xf0'产生异常。b'\xf0'[0]是该序列中的第一个(也是唯一一个)字节,它被接受为&.
  • 编辑:您在评论中澄清了您只希望inp_bytes在前导零的数量完全等于n--logic 时返回以检查下一个半字节是否非零。

考虑到所有这些,这是我的解决方案:

def search_zeros(inp_bytes, n):
    if len(inp_bytes) < (n+1)//2:
        return None
    if any(y for y in inp_bytes[:n//2]):
        return None
    if n % 2 != 0 and inp_bytes[n//2] & b'\xf0'[0] != 0:
        return None
    # Make sure the next nibble is not zero:
    if n % 2 != 0:
        if inp_bytes[n//2] & b'\x0f'[0] != 0:
            return inp_bytes
    else:
        if len(inp_bytes) == n//2 or inp_bytes[n//2] & b'\xf0'[0] != 0:
            return inp_bytes
    return None


x=b'\x00\x00\x03\x44'
for n in range(10):
    print(f"n={n} x={x} result={search_zeros(x, n)}")

x=b'\x00'
for n in range(5):
    print(f"n={n} x={x} result={search_zeros(x, n)}")

x=b'\x00\x10'
for n in range(5):
    print(f"n={n} x={x} result={search_zeros(x, n)}")

x=b'\x00\x01'
for n in range(5):
    print(f"n={n} x={x} result={search_zeros(x, n)}")

输出:

n=0 x=b'\x00\x00\x03D' result=None
n=1 x=b'\x00\x00\x03D' result=None
n=2 x=b'\x00\x00\x03D' result=None
n=3 x=b'\x00\x00\x03D' result=None
n=4 x=b'\x00\x00\x03D' result=None
n=5 x=b'\x00\x00\x03D' result=b'\x00\x00\x03D'
n=6 x=b'\x00\x00\x03D' result=None
n=7 x=b'\x00\x00\x03D' result=None
n=8 x=b'\x00\x00\x03D' result=None
n=9 x=b'\x00\x00\x03D' result=None
n=0 x=b'\x00' result=None
n=1 x=b'\x00' result=None
n=2 x=b'\x00' result=b'\x00'
n=3 x=b'\x00' result=None
n=4 x=b'\x00' result=None
n=0 x=b'\x00\x10' result=None
n=1 x=b'\x00\x10' result=None
n=2 x=b'\x00\x10' result=b'\x00\x10'
n=3 x=b'\x00\x10' result=None
n=4 x=b'\x00\x10' result=None
n=0 x=b'\x00\x01' result=None
n=1 x=b'\x00\x01' result=None
n=2 x=b'\x00\x01' result=None
n=3 x=b'\x00\x01' result=b'\x00\x01'
n=4 x=b'\x00\x01' result=None

推荐阅读