【问题标题】:what is the correct way to process 4 bits inside an octet in python在python中处理八位字节内的4位的正确方法是什么
【发布时间】:2009-10-19 08:18:26
【问题描述】:

我正在编写一个应用程序来解析某些网络数据包。数据包字段包含八位字节中的协议版本号,因此高 4 位是“主要”版本,低 4 位是“次要”版本。目前我正在按如下方式解析它们,但我想知道是否有更漂亮或更“pythonic”的方式:

    v = ord(data[17])
    major = (v & int('11110000',2) ) >> 4
    minor = v & int('00001111',2)

【问题讨论】:

    标签: python bit-manipulation


    【解决方案1】:

    你可以像这样写二进制字面量0b1111000

    对于您的示例,我可能会使用十六进制

    v = ord(data[17])
    major = (v & 0xF0) >> 4
    minor = (v & 0x0F)
    

    您可能还想使用struct 模块将数据包分解成组件

    【讨论】:

    • 0v11110000 不起作用,因为我坚持使用 2.4 python,但使用十六进制是有意义的,谢谢
    【解决方案2】:

    命名良好的函数始终是隐藏丑陋和无关复杂性的好方法。这样,bit-fiddling 仅限于小的且易于证明的正确函数,而更高级别的代码可以参考 fiddleing 的目的。

    def high_nibble(byte):
        """Get 4 high order bits from a byte."""
        return (byte >> 4) & 0xF
    
    def low_nibble(byte):
        """Get 4 low order bits from a byte."""
        return byte & 0xF
    
    def parse_version(version_byte):
        """Get the major-minor version tuple from the version byte."""
        return high_nibble(version_byte), low_nibble(version_byte)
    
    major, minor = parse_version(version_byte)
    

    【讨论】:

      【解决方案3】:

      使用文字而不是调用int 会更简洁。您可以使用二进制文字或十六进制,例如:

      major = (v & 0xf0) >> 4
      minor = (v & 0x0f)
      

      二进制文字仅适用于 Python 2.6 或更高版本,格式为 0b11110000。如果您使用的是 Python 2.6 或更高版本,那么您可能需要查看 bytearray 类型,因为这可以让您将数据视为二进制,因此不必使用对 ord 的调用。

      如果您正在解析二进制数据并发现您必须进行大量的位操作,那么您可能想尝试一个更通用的解决方案,因为有一些第三方模块专门处理这个问题。一个是hachoir,一个较低级别的替代方案是bitstring(我写的)。在这种情况下,您的解析将变为:

      major, minor = data.readlist('uint:4, uint:4')
      

      如果您进行大量此类读取,这会更容易管理。

      【讨论】:

        【解决方案4】:

        提示一下,你最好移位后应用主要的掩码,以防它是负数并保留符号:

        major = (v >> 4) & 0x0f
        minor = (v & 0x0f)
        

        【讨论】:

        • 您的语法似乎无效,我认为 ord 只会返回一个正数。
        • 我很高兴看到您能够很好地发现错别字...在使用位掩码时,最好确保您的代码能够抵御接口更改等意外事件(我没想到ord 改变,但这个 sn-p 不太可能被重构,并且在左移时出现由符号扩展引起的错误比无效语法更难发现)
        • 抱歉,我看不出(v >> 4) & 0x0f 何时会与(v & 0xf0) >> 4 不同(你能举个例子吗?)。在某些语言中,左移(而不是右移)可能会导致设置最高位,这可能会改变符号,但 Python 中的整数不会发生这种情况。
        • 我的意思是右移...我没太注意。确实,在 Python 中不太容易发生这种情况(因为它会自动向上转换为 longints 并裁剪符号),但在转换后屏蔽以保持代码在其他语言中的意义以及与 C 接口的情况仍然是一个好习惯通过 CTypes,例如...
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-04
        • 2013-09-02
        • 2020-03-23
        相关资源
        最近更新 更多