На этом шаге мы рассмотрим работу с байтовыми строками.
Вы хотите выполнить стандартные текстовые операции (срезание символов, поиск, замену) над строками байтов.
Байтовые строки поддерживают большую часть тех же встроенных операций, что и текстовые строки. Например:
>>> data = b'Hello World' >>> data[0:5] b'Hello' >>> data.startswith(b'Hello') True >>> data.split() [b'Hello', b'World'] >>> data.replace(b'Hello', b'Hello Cruel') b'Hello Cruel World' >>>
Такие операции можно проделать и над байтовыми массивами:
>>> data = bytearray(b'Hello World') >>> data[0:5] bytearray(b'Hello') >>> data.startswith(b'Hello') True >>> data.split() [bytearray(b'Hello'), bytearray(b'World')] >>> data.replace(b'Hello', b'Hello Cruel') bytearray(b'Hello Cruel World') >>>
Вы можете просто применить к байтовым строкам поиск совпадений с помощью регулярных выражений, но сами шаблоны должны быть определены как байты. Например:
>>> data = b'FOO:BAR,SPAM' >>> import re >>> re.split('[:,]',data) Traceback (most recent call last): . . . . TypeError: cannot use a string pattern on a bytes-like object >>> re.split(b'[:,]',data) # Обратите внимание: шаблон в байтах [b'FOO', b'BAR', b'SPAM'] >>>
Практически все доступные для текстовых строк операции будут работать и на байтовых строках. Однако есть несколько заметных отличий, о которых нужно знать. Во-первых, при индексировании байтовых строк мы получаем целые числа, а не символы. Например:
>>> a = 'Hello World' # Текстовая строка >>> a[0] 'H' >>> a[1] 'e' >>> b = b'Hello World' # Байтовая строка >>> b[0] 72 >>> b[1] 101 >>>
Эта разница в семантике может влиять на программы, которые пытаются обработать байтовые данные так же, как и текстовые.
Во-вторых, байтовые строки не предоставляют красивые строковые представления и не выводятся в симпатичном виде, если сначала не проведено декодирование в текстовую строку. Например:
>>> s = b'Hello World' >>> print(s) b'Hello World' >>> print(s.decode('ascii')) Hello World >>>
Строковая операция format() недоступна для байтовых строк.
>>> b'%10s %10d %10.2f' % (b'ACME', 100, 490.1) b' ACME 100 490.10' >>> b'{} {} {}'.format(b'ACME', 100, 490.1) Traceback (most recent call last): . . . . AttributeError: 'bytes' object has no attribute 'format' >>>
Если вы хотите применить какое-то форматирование к байтовой строке, это должно быть проделано с помощью обычных текстовых строк и последующего кодирования. Например:
>>> '{:10s} {:10d} {:10.2f}'.format('ACME', 100, 490.1).encode('ascii') b'ACME 100 490.10' >>>
И наконец, вы должны знать, что использование байтовых строк может изменить семантику некоторых операций, особенно тех, что относятся к файловой системе. Например, если вы предоставляете имя файла закодированным в байтовую строку, а не в текстовую, это обычно отключает кодирование и декодирование имени файла. Например:
>>> # Запишем имя файла в UTF-8 >>> with open('jalape\xf1o.txt', 'w') as f: f.write('spicy') 5 >>> # Получим содержимое каталога >>> import os >>> os.listdir('.') # Текстовая строка (имена декодированы) [..., 'jalapeño.txt', ...] >>> os.listdir(b'.') # Байтовая строка (имена остались байтами) [..., b'jalapen\xcc\x83o.txt', ...] >>>
Посмотрите, как в последней части этого примера передача имени каталога в виде байтовой строки вызывает возврат имен файлов в виде недекодированных байтов.
Имя файла, показанное в списке содержимого каталога, содержит "сырую" кодировку UTF-8.
Некоторые программисты могут склоняться к использованию байтовых строк в качестве альтернативы текстовым из-за возможного выигрыша в производительности. Да, операции над байтами могут быть немного более эффективными, чем работа с текстом (из-за расходов на Unicode), однако такой подход приводит к грязному и неидиоматическому коду. Вы будете часто сталкиваться с тем, что байтовые строки не очень хорошо сочетаются с другими частями Python, и закончите тем, что будете вручную выполнять всевозможные операции кодирования-декодирования, чтобы все работало. Так что если вы работаете с текстом, используйте обычные текстовые строки, а не байтовые.
Со следующего шага мы начнем рассматривать работу с числами, датами и временем.