Типы bytes и bytearray в python

Типы bytes и bytearray в python

https://t.me/learnpythonforfun (Denis Obrezkov)

Мотивация

Python часто используется для различных манипуляций с данными, типичный пример работы: считать данные от пользователя, запаковать их в запрос, отправить данные на сервер. Иногда такие запакованные данные предстают не в виде текста, а в виде последовательностей нулей и единиц, с которыми, однако, программисту надо как-то работать. В таких случаях выручают объекты bytes и bytearray.

О байтах и битах

Биты и байты считаются единицами измерения информации. Двоичный бит принимает два значения: ноль и единица. Используя бит мы можем закодировать только два состояния, но если мы используем два бита подряд, то таких состояний уже будет четыре: 00, 01, 10, 11. Мы можем даже закодировать маленький алфавит: А - 00, Б - 01, В - 10, Г - 11. Эти двоичные последовательности, также соответствуют двоичным представлениям чисел 0, 1, 2, 3.

Байт — это единица измерения информации, в типичном современном компьютере состоящая из восьми бит. Вот примеры байтов: 10010101, 00000001, 11111111, 00000000. Эти байты позволяют закодировать числа от 0 до 255. Соответственно, они позволяют закодировать даже весь алфавит. Так, к примеру, и сделано в ASCII таблице, которая использует 7 бит:

Зачем такая кодировка нужна? Если говорить очень грубо, то так как по проводам мы можем передавать только условно низкий (0) и высокий (1) уровни напряжения, то и все передаваемое мы должны кодировать нулями и единицами.

Тип bytes в python

Для работы с последовательностями нулей и единиц, в python есть тип bytes. Он является неизменяемым, а его создание происходит следующим образом:

>>> binary_obj = b'These are some bytes'
>>> print(binary_obj)
b'This are some bytes'

Обратите внимание, что инициализация отличается от строкового объекта:

>>> string_obj = 'These are some letters'
>>> print(string_obj)
This are some letters

Типы созданных объектов тоже будут разными:

>>> print(type(binary_obj))
<class 'bytes'>

>>> print(type(string_obj))
<class 'str'>

Байтовый объект можно получить и из строки,указав её кодировку:

>>> bytes(string_obj, encoding='utf-8')
b'This are some letters'

Кроме этого, байтовый объект можно инициализировать нулями:

>>> bytes(10)
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

перечисляемым набором целых чисел:

>>> bytes(range(16))
b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f'

или неким бинарным объектом. 


Так как объекты byte неизменяемые, то их часто применяют при написании тестов, там, где требуются наперед заданные нетекстовые значения, к примеру, при тестировании криптографических библиотек. Часто же, больший интерес представляет изменяемый аналог byte - bytearray.

Тип bytearray в python

Объекты bytearray являются изменяемой альтернативой объектам bytes. К примеру, если в объекте bytes мы попытаемся на место второго байта подставить байт со значением f (со значением в таблице кодировки 102), то для объекта bytes будет выдана ошибка :

>>> a = b"abc"
>>> a[1] = 102

TypeError: 'bytes' object does not support item assignment

а для bytearray ошибки не будет:

>>> b = bytearray('abc', encoding='utf-8')
>>> b[1] = 102
>>> b
bytearray(b'afc')

Оба класса bytes и bytearray имеют операции обычных последовательностей, такие как: capitalize(), isdigit(), split(), strip() и т.д. Одной из отличительных особенностей этих типов является тип возвращаемых значений по срезу и по индексу. К примеру, для строки в обоих случаях возвращаемый тип будет строкой:

>>> print(str1[4], type(str1[4]))
o <class 'str'>

>>> print(str1[4:5], type(str1[4:5]))
o <class 'str'>

Для типа байт, обращение по индексу вернет целочисленное значение, соответствующее элементу, а срез - объект типа bytes с тем запрошенным элементом:

>>> print(byte1[4], type(byte1[4]))
111 <class 'int'>

>>> print(byte1[4:5], type(byte1[4:5]))
b'o' <class 'bytes'>

Заключение

Мы рассмотрели классы bytes и bytearray. Эти классы позволяют работать с байтовыми представлениями данных, при этом первый является неизменяемым, а второй является изменяемым аналогом первого. Оба этих типа часто используются при тестировании программ, там где нужно подать сырые данные на вход программе, к примеру, в ручную сформированный “сломанный” пакет данных или криптографический ключ, обладающий необходимыми свойствами.

Report Page