如何在一个字节中设置位对象以表示Python中的十六进制符号

时间:2018-09-27 11:30:14

标签: python arrays hex byte bit

我想替换表示十六进制符号的字节类型对象中的单个符号。

print(type(a)) # --> <class 'bytes'>

a = b'2900BC'开始,我想通过调用一些类似于

的函数来以类似a = b'29F0BC'的形式结束
replace_hex_symbol(input, index, value)

就我而言

replace_hex_symbol(a,2,F)

意味着将对象a中的符号编号2设置为F的值(因为f_hex = 1111_bin)

据我了解,一个问题是字节类型的对象是不可变的。即使将其转换为字节数组,我似乎也无法完成。 python中是否已经有一种好的方法来实现这种操作,或者有人巧妙地技巧了如何替换该对象中充满十六进制符号的部分?

1 个答案:

答案 0 :(得分:0)

bytes对象通常具有与字符串相同的方法。两者都是不可变的,但这不会阻止您根据旧值创建新对象。

例如,您可以创建一个新的bytes值,将所有2个ASCII字符替换为F的ASCII字符并替换为bytes.replace() method

>>> b'2900BC'.replace(b'2', b'F')
b'F900BC'

有关受支持的方法列表,请参见Python标准类型文档的Bytes and Bytearray Operations section。请注意,bytes.replace()的参数本身必须带有bytes值!

根据您的replace_hex_symbol()函数:

def replace_hex_symbol(a, old, new):
    # ensure that both old and new are actually bytes
    if not isinstance(old, bytes):
        old = old.encode('ascii')
    if not isinstance(new, bytes):
        new = new.encode('ascii')
    return a.replace(old, new)

接下来,bytearray对象基本上是bytes的可变子类;它们具有相同的方法,但是您也可以直接处理索引并进行更新。参见Mutable Sequence Types documentation

bytesbytearray对象都是0-255范围内的整数的序列,索引可以反映这一点。分配给bytearray的单个索引时,必须使用整数:

>>> b = bytearray(b'2900BC')
>>> b
bytearray(b'2900BC')
>>> b[0]
50
>>> b[0] = ord('F')  # ascii codepoint for F
>>> b
bytearray(b'F900BC')

,但是您也可以使用切片(包括分配)进行索引,这时您在获取时会再次获得相同的序列对象,并且可以接受任何字节序列(包括bytes对象或整数列表)

但是,当您要替换十六进制字符时,索引更新就地访问bytesarray会变得更加麻烦。

实际上,关于十六进制字符序列,没有任何内容声明它们必须为bytes值!如果必须具有可变类型,则也可以使用str对象或单个十六进制数字列表:

>>> '2900BC'  # string
'2900BC'
>>> list('2900BC')  # list of characters
['2', '9', '0', '0', 'B', 'C']

如果您要以十六进制数字处理已被编码的二进制数据,请使用bytes.fromhex() factory method将该编码数据转换为bytes值,然后返回{{ 3}}; bytearray个对象支持相同的转换。

此时,十六进制数字将分别转换为4位半字节,并且您需要均匀的十六进制数字长度:

>>> bytes.fromhex('2900BC')
b')\x00\xbc'
>>> list(bytes.fromhex('2900BC'))  # show individual byte integer values
[41, 0, 188]

,您必须使用位移和掩码来设置单个半字节。例如,输入十六进制中的2是第一个字节中最重要的半字节,因此F十六进制或15十进制将需要移位4位,并且然后与第一个字节的低4位组合:

>>> a = bytearray.fromhex('2900BC')  # mutable sequence of 3 bytes
>>> a[0] = (0xF << 4) | (a[0] & 0xF)  # set upper nibble, preserve lower
>>> a
bytearray(b'\xf9\x00\xbc')
>>> a.hex()
'f900bc'

请参阅Python Wiki上的bytes.hex()。但是,如果您需要更大规模的操作,请考虑使用bit manipulation page之类的第三方库来简化操作。