在python中,处理八位字节中的4位的正确方法是什么

在python中,处理八位字节中的4位的正确方法是什么,python,bit-manipulation,Python,Bit Manipulation,我正在编写一个应用程序来解析某些网络数据包。数据包字段包含八位字节中的协议版本号,因此4个高位为“主要”版本,4个低位为“次要”版本。目前,我正在对它们进行如下解析,但我想知道是否有一种更漂亮或更“python”的方法: v = ord(data[17]) major = (v & int('11110000',2) ) >> 4 minor = v & int('00001111',2) 您可以像这样编写二进制文本0b1111000 作为你

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

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

您可以像这样编写二进制文本
0b1111000

作为你的例子,我可能会使用十六进制

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

您可能还希望使用模块将数据包分解为其组件

您可以编写如下的二进制文本
0b1111000

作为你的例子,我可能会使用十六进制

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

您可能还希望使用模块将数据包分解为其组件

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

major = (v & 0xf0) >> 4
minor = (v & 0x0f)
二进制文字仅适用于Python 2.6或更高版本,其形式为
0b11110000
。如果您使用的是Python 2.6或更高版本,那么您可能需要查看
bytearray
类型,因为这样可以将数据视为二进制数据,因此不必使用对
ord
的调用

如果您正在解析二进制数据,并且发现必须进行大量逐位操作,那么您可能希望尝试更通用的解决方案,因为有一些第三方模块专门从事这方面的工作。一个是,一个较低级别的备选方案是(我写的)。在这种情况下,您的解析将类似于:

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

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

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

major = (v & 0xf0) >> 4
minor = (v & 0x0f)
二进制文字仅适用于Python 2.6或更高版本,其形式为
0b11110000
。如果您使用的是Python 2.6或更高版本,那么您可能需要查看
bytearray
类型,因为这样可以将数据视为二进制数据,因此不必使用对
ord
的调用

如果您正在解析二进制数据,并且发现必须进行大量逐位操作,那么您可能希望尝试更通用的解决方案,因为有一些第三方模块专门从事这方面的工作。一个是,一个较低级别的备选方案是(我写的)。在这种情况下,您的解析将类似于:

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

如果你做了很多这样的阅读,这会更容易管理。

只要一个提示,你最好在移位后为大调应用掩码,以防它是负数并且符号保持不变:

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

只要一个提示,你最好在移位后为大调加上口罩,以防它是负数并且符号保持不变:

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

命名良好的函数总是隐藏丑陋和不相关复杂性的好方法。通过这种方式,位篡改仅限于小的且易于验证的正确函数,而更高级别的代码可以引用篡改的目的

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)

命名良好的函数总是隐藏丑陋和不相关复杂性的好方法。通过这种方式,位篡改仅限于小的且易于验证的正确函数,而更高级别的代码可以引用篡改的目的

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)

0v11110000在我使用2.4 python时不起作用,但使用十六进制是有意义的,thanks0v11110000在我使用2.4 python时不起作用,但使用十六进制是有意义的,Thanksy您的语法似乎无效,我认为ord只会返回一个正数。我很高兴看到您很好地发现了打字错误。。。在使用位掩码时,最好确保您的代码对诸如接口更改之类的突发事件具有鲁棒性(我不希望ord发生更改,但这段代码不太可能被重构,并且在左移时出现由符号扩展引起的错误比无效语法更难发现)对不起,但是我看不出什么时候
(v>>4)&0x0f
会与
(v&0xf0)>>4
有所不同(你能举个例子吗?)。在某些语言中,左移(而不是右移)可能会导致设置一个顶部位,这可能会改变符号,但Python中的整数不会发生这种情况。。。我没怎么注意。确实,在Python中,这种情况不太容易发生(因为它会自动向上转换到longints并裁剪符号),但在转换后屏蔽代码仍然是一种很好的做法,以保持代码在其他语言中的意义,例如,在通过CTypes与C交互的情况下……您的语法似乎无效,而且我认为ord只会返回一个正数。我很高兴看到你能很好地识别打字错误。。。在使用位掩码时,最好确保您的代码对诸如接口更改之类的突发事件具有鲁棒性(我不希望ord发生更改,但这段代码不太可能被重构,并且在左移时出现由符号扩展引起的错误比无效语法更难发现)对不起,但是我看不出什么时候
(v>>4)&0x0f
会与
(v&0xf0)>>4
有所不同(你能举个例子吗?)。在某些语言中,左移(而不是右移)可能会导致设置一个顶部位,这可能会改变符号,但Python中的整数不会发生这种情况。。。我没怎么注意。确实,在Python中,这种情况不太容易发生(因为它会自动向上转换到longints并裁剪符号),但在转换后屏蔽代码仍然是一种很好的做法,以保持代码在其他语言中的意义,例如,在通过CTypes与C接口的情况下。。。