bytes
объекты обычно имеют те же методы, что и строки;оба являются неизменяемыми, но это не мешает вам создавать новые объекты на основе старого значения.
Например, вы можете создать новое значение bytes
со всеми символами 2
ASCII, замененными на F
Символ ASCII с методом bytes.replace()
:
>>> b'2900BC'.replace(b'2', b'F')
b'F900BC'
См. Операции с байтами и байтами раздел документации по стандартным типам Pythonдля списка методов, которые поддерживаются.Обратите внимание, что аргументы 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
;у них те же методы, но вы также можете напрямую обращаться к индексам и обновлять их.См. Типы изменяемых последовательностей Документация .
Оба объекта bytes
и bytearray
являются последовательностями целых чисел в диапазоне 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
с помощью bytes.fromhex()
фабричного метода и вернитесь к bytes.hex()
;bytearray
объекты поддерживают одинаковые преобразования.
В этот момент шестнадцатеричные цифры преобразуются в 4-битные полубайты каждый, и вам нужна четная длина шестнадцатеричных цифр:
>>> bytes.fromhex('2900BC')
b')\x00\xbc'
>>> list(bytes.fromhex('2900BC')) # show individual byte integer values
[41, 0, 188]
и выпришлось бы использовать битовое смещение и маскировку , чтобы установить отдельные клевы.Например, 2
во входном шестнадцатеричном коде является наиболее значимым полубайтом в первом байте, поэтому F
hex или 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.Однако, если вам нужен этот уровень манипуляции в более широком масштабе, рассмотрите стороннюю библиотеку, такую как bitstring
, чтобы упростить вам эту задачу.