Шаг 48.
Основы языка Python.
Строки и двоичные данные. Тип данных bytes

    На этом шаге мы рассмотрим назначение, задание и использование этого типа данных.

    Тип данных str отлично подходит для хранения текстовой информации, но что делать, если необходимо обрабатывать изображения? Ведь изображение не имеет кодировки, а значит, оно не может быть преобразовано в Unicode-строку. Для решения этой проблемы в Python 3 были введены типы bytes и bytearray, которые позволяют хранить последовательность целых чисел в диапазоне от 0 до 255. Каждое такое число обозначает код символа. Тип данных bytes относится к неизменяемым типам, как и строки, а тип данных bytearray - к изменяемым, как и списки.

    Создать объект типа bytes можно следующими способами:

    Объекты типа bytes относятся к последовательностям. Каждый элемент такой последовательности может хранить целое число от 0 до 255, которое обозначает код символа. Как и все последовательности, объекты поддерживают обращение к элементу по индексу, получение среза, конкатенацию, повторение и проверку на вхождение:

>>> b = bytes("string", "cp1251")
>>> b
b'string'
>>> b[0]         # Обращение по индексу
115
>>> b[1:3]       # Получение среза
b'tr'
>>> b + b"123"   # Конкатенация
b'string123'
>>> b * 3        # Повторение
b'stringstringstring'
>>> 115 in b, b"tr" in b, b"as" in b
(True, True, False)

    Как видно из примера, при выводе объекта целиком, а также при извлечении среза, производится попытка отображения символов. Однако доступ по индексу возвращает целое число, а не символ. Если преобразовать объект в список, то мы получим последовательность целых чисел:

>>> list(bytes("string", "cp1251"))
[115, 116, 114, 105, 110, 103]

    Тип bytes относится к неизменяемым типам. Это означает, что можно получить значение по индексу, но изменить его нельзя:

>>> b = bytes("string", "cp1251")
>>> b[0] = 168
Traceback (most recent call last):
  File "<pyshell#4>", line 1, in <module>
    b[0] = 168
TypeError: 'bytes' object does not support item assignment

    Объекты типа bytes поддерживают большинство строковых методов, которые мы рассматривали на предыдущих шагах. Однако некоторые из этих методов могут некорректно работать с русскими буквами - в этих случаях следует использовать тип str, а не тип bytes. Не поддерживаются объектами типа bytes строковые методы encode(), isidentifier(), isprintable(), isnumeric(), isdecimal(), format_map() и format(), а также операция форматирования.

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

>>> b = bytes("string", "cp1251")
>>> b.replace(b"s", b"S")
b'String'

    Необходимо также помнить, что смешивать строки и объекты типа bytes в выражениях нельзя. Предварительно необходимо явно преобразовать объекты к одному типу, а лишь затем производить операцию:

>>> b"string" + "string"
Traceback (most recent call last):
  File "<pyshell#11>", line 1, in <module>
    b"string" + "string"
TypeError: can't concat str to bytes
>>> b"string" + "string".encode('ascii')
b'stringstring'

    Объект типа bytes может содержать как однобайтовые символы, так и многобайтовые. При использовании многобайтовых символов некоторые функции могут работать не так, как вы думаете, - например, функция len() вернет количество байтов, а не символов:

>>> len("строка")
6
>>> len(bytes("строка", "cp1251"))
6
>>> len(bytes("строка", "utf-8"))
12

    Преобразовать объект типа bytes в строку позволяет метод decode(). Метод имеет следующий формат:

  decode([encoding="utf-8"][, errors="strict"])

    Параметр encoding задает кодировку символов (по умолчанию UTF-8) в объекте bytes, a параметр errors - способ обработки ошибок при преобразовании. В параметре errors можно указать значения "strict" (значение по умолчанию), "replace" или "ignore". Пример преобразования:

>>> b = bytes("строка", "cp1251")
>>> b.decode(encoding="cp1251"), b.decode("cp1251")
('строка', 'строка')

    Для преобразования можно также воспользоваться функцией str():

>>> b = bytes("строка", "cp1251")
>>> str(b, "cp1251")
'строка'

    Чтобы изменить кодировку данных, следует сначала преобразовать тип bytes в строку, а затем произвести обратное преобразование, указав нужную кодировку. Преобразуем данные из кодировки Windows-1251 в кодировку KOI8-R, а затем обратно:

>>> w = bytes("Строка", "cp1251") # Данные в кодировке windows-1251
>>> k = w.decode("cp1251").encode('koi8-r')
>>> k, str(k, 'koi8-r') # Данные в кодировке koi8-r
(b'\xf3\xd4\xd2\xcf\xcb\xc1', 'Строка')
>>> w = k.decode("koi8-r").encode('cp1251')
>>> w, str(w, 'cp1251') # Данные в кодировке windows-1251
(b'\xd1\xf2\xf0\xee\xea\xe0', 'Строка')

    На следующем шаге мы рассмотрим тип данных bytearray.




Предыдущий шаг Содержание Следующий шаг