Python中的位掩码

时间:2011-12-14 17:18:28

标签: python bit-manipulation

我有一个字节(来自其他供应商),潜在的位掩码如下:

value1 = 0x01 value2 = 0x02 value3 = 0x03 value4 = 0x04 value5 = 0x05 value6 = 0x06 value7 = 0x40 value8 = 0x80

我可以指望value1到value6中的一个存在。然后可以设置或不设置value7。 value8可能已设置,也可能未设置。

所以这是合法的:value2 | value7 | value8 这不合法:value1 | value3 | value7

我需要弄清楚是否设置了值7,是否设置了value8,以及剩下的值是什么。

我有以下python代码。有更优雅的方式吗?

value1 = 0x01
value2 = 0x02
value3 = 0x03
value4 = 0x04
value5 = 0x05
value6 = 0x06
value7 = 0x40
value8 = 0x80

def format_byte_as_bits(value):
    return format(value,'b').zfill(8)

def mask_bits_on_byte(byte,mask):
    inverse_of_mask = mask ^ 0b11111111
    return byte & inverse_of_mask

def parse_byte(byte):

    value7_set = byte & value7 == value7
    value8_set = byte & value8 == value8
    byte = mask_bits_on_byte(byte,value7)
    byte = mask_bits_on_byte(byte,value8)
    base_value = byte
    return value7_set,value8_set,base_value

# Example 1
byte = value3 | value7
value7_set,value8_set,base_value = parse_byte(byte)
print("base_value = "+str(base_value))
print("value7_set = "+str(value7_set))
print("value8_set = "+str(value8_set))
print()

# Output:
# base_value = 3
# value7_set = True
# value8_set = False

# Example 2
byte = value5
value7_set,value8_set,base_value = parse_byte(byte)
print("base_value = "+str(base_value))
print("value7_set = "+str(value7_set))
print("value8_set = "+str(value8_set))
print()

# Output:
# base_value = 5
# value7_set = False
# value8_set = False

# Example 3
byte = value1 | value7 | value8
value7_set,value8_set,base_value = parse_byte(byte)
print("base_value = "+str(base_value))
print("value7_set = "+str(value7_set))
print("value8_set = "+str(value8_set))

# Output:
# base_value = 1
# value7_set = True
# value8_set = True

编辑 - 我喜欢stackoverflow。这么多有用的答案,这么快!你们真棒!希望我能标出所有的答案。但我至少会给大家一个投票!

EDIT2 - 根据以下答案,代码简化为以下内容:

value1 = 0x01
value2 = 0x02
value3 = 0x03
value4 = 0x04
value5 = 0x05
value6 = 0x06
value7 = 0x40
value8 = 0x80

def parse_byte(byte):
    return byte & value7, byte & 0x80, byte & 7

# Example 1
byte = value3 | value7
value7_set,value8_set,base_value = parse_byte(byte)
print("base_value = "+str(base_value))
if value7_set: print("value7_set")
if value8_set: print("value8_set")
print()

# Example 2
byte = value5
value7_set,value8_set,base_value = parse_byte(byte)
print("base_value = "+str(base_value))
if value7_set: print("value7_set")
if value8_set: print("value8_set")
print()

# Example 3
byte = value1 | value7 | value8
value7_set,value8_set,base_value = parse_byte(byte)
print("base_value = "+str(base_value))
if value7_set: print("value7_set")
if value8_set: print("value8_set")
print()

4 个答案:

答案 0 :(得分:12)

您的大多数value*常量实际上并不是位掩码,只有value7value8。我定义了另一个位掩码来提取低位,所以我总共有三个位掩码:

mask0 = 0x07
mask1 = 0x40
mask2 = 0x80

现在您的功能变为

def parse_byte(byte):
    return byte & mask2, byte & mask1, byte & mask0

我没有将结果转换为bool - 我不明白为什么这是必要的。使用if检查返回的值时,无论如何都会隐式转换为bool

另请注意

format(value,'b').zfill(8)

可以简化为

format(value,'08b')

答案 1 :(得分:5)

给出如下值:

>>> x = 0b10001000

您可以查看最高位是否设置为:

>>> bit8 = bool(x & 0b10000000)
>>> bit7 = bool(x & 0b01000000)

要查找设置了哪个较低位,请使用字典:

>>> bdict = dict((1<<i, i+1) for i in range(6))
>>> bdict[x & 0b00111111]
4

答案 2 :(得分:3)

您不需要其他两个功能:

def parse_byte(byte):
    value7_set = byte & value7 == value7
    value8_set = byte & value8 == value8
    base_value =  byte & 7
    return value7_set,value8_set,base_value

答案 3 :(得分:1)

它有点冗长但完全没问题。我所做的唯一改变是简化parse_byte:

def parse_byte(byte):

     value7_set = byte & value7 == value7
     value8_set = byte & value8 == value8
     base_value = mask_bits_on_byte(byte,value7 | value8)
     return value7_set,value8_set,base_value