Тип данных bytes
- это неизменяемые последовательности отдельных байтов. Основные двоичные протоколы основаны на кодировании текста ASCII
.
Синтаксис для байтовых литералов в основном такой же, как и для строковых литералов, за исключением того, что добавляется префикс 'b'
:
Как и в случае строковых литералов, байтовые литералы могут также использовать префикс 'r'
для отключения обработки escape-последовательностей.
Помимо литеральных форм, объекты bytes
могут быть созданы с помощью встроенного класса bytes()
:
bytes(10)
.bytes(range(20))
.bytes(obj)
.В то время как байтовые литералы основаны на тексте ASCII
, байтовые объекты фактически ведут себя как неизменяемые последовательности целых чисел, причем каждое значение в последовательности ограничено таким образом, что 0 <= x < 256
, попытки нарушить это ограничение вызовут ValueError
. Это сделано специально, чтобы подчеркнуть, что слепое применение алгоритмов обработки текста к двоичным форматам данных, которые не совместимы с ASCII, обычно приводит к повреждению данных.
Для байтовых строк доступны следующие операции:
Две шестнадцатеричные цифры точно соответствуют одному байту и по этому шестнадцатеричные числа являются широко используемым форматом для описания двоичных данных. Соответственно, тип bytes
имеет дополнительный метод класса для чтения данных в этом формате:
bytes.fromhex(string)
::Метод bytes.fromhex()
возвращает объект bytes
, декодируя данный строковый объект. Строка должна содержать две шестнадцатеричные цифры на байт, при этом пробелы ASCII
игнорируются.
>>> bytes.fromhex('2Ef0 F1f2 ')
# b'.\xf0\xf1\xf2'
bytes.hex()
::Метод bytes.hex()
преобразовывает объект bytes
в его шестнадцатеричное представление. Возвращает строковый объект, содержащий две шестнадцатеричные цифры для каждого байта.
>>> b'\xf0\xf1\xf2'.hex()
# 'f0f1f2'
В Python-3.8 метод bytes.hex()
поддерживает необязательные параметры sep
и bytes_per_sep
для вставки разделителей между байтами в шестнадцатеричный вывод.
Если нужно облегчить чтение шестнадцатеричной строки, можно указать параметр sep
разделителя из одного символа для включения в вывод. По умолчанию между каждым байтом. Второй необязательный параметр bytes_per_sep
управляет интервалом. Положительные значения вычисляют положение разделителя справа, отрицательные значения слева.
>>> value = b'\xf0\xf1\xf2'
>>> value.hex('-')
# 'f0-f1-f2'
>>> value.hex('_', 2)
# 'f0_f1f2'
>>> b'UUDDLRLRAB'.hex(' ', -4)
#'55554444 4c524c52 4142'
Важно: Поскольку байтовые объекты являются неизменяемыми последовательностями целых чисел (подобно кортежу), то для байтового объекта 'b'
, b[0]
будет целым числом, а b[0:1]
- байтовым объектом длины 1. Это контрастирует с текстовыми строками, где индексация и срез будут производить строку длиной 1 символ.
Представление объектов bytes
использует литеральный формат (b'...')
так как это часто более полезно и наглядно, чем, например, bytes([46, 46, 46])
. Вы всегда можете преобразовать объект bytes
в список целых чисел с помощью list(b).
>>> b = bytes([46, 46, 46])
>>> b
# b'...'
>>> list(b)
# [46, 46, 46]
>>> b = bytes(range(40,60,2))
>>> b
# b'(*,.02468:'
>>> list(b)
[40, 42, 44, 46, 48, 50, 52, 54, 56, 58]