Строковые литералы определяются с помощью одинарных, двойных или тройных кавычек.
Добавление символа b или B перед открывающей кавычкой в любой из этих форм приводит к созданию объекта типа bytes.
>>> B = b'solaris'
>>> type(B), type(S)
( < class 'bytes' >, < class 'str' > )
>>>
Добавление символа b или B перед открывающей кавычкой в любой из этих форм приводит к созданию объекта типа bytes.
>>> B = b'solaris'
>>> type(B), type(S)
( < class 'bytes' >, < class 'str' > )
>>>
b'solaris'
>>> S
'oracle'
>>>
В действительности тип byte - это последовательность целых чисел.
>>> B[0], S[0]
(115, 'o')
>>> B[1:], S[1:]
(b'olaris', 'racle')
>>> list(B), list(S)
([115, 111, 108, 97, 114, 105, 115], ['o', 'r', 'a', 'c', 'l', 'e'])
>>>
Типы byte и srt неизменяемые:
>>> B[0] = 'Z'
Traceback (most recent call last):
File "
B[0] = 'Z'
TypeError: 'bytes' object does not support item assignment
>>>
>>> S[0] = 'Z'
Traceback (most recent call last):
File "
S[0] = 'Z'
TypeError: 'str' object does not support item assignment
>>>
Кодирование строк символов ASCII:
>>> ord('o')
111
>>> chr(111)
'o'
>>> S = 'oracle'
>>> S
'oracle'
>>> len(S)
6
>>> [ord(i) for i in S]
[111, 114, 97, 99, 108, 101]
>>> S.encode('ascii')
b'oracle'
>>> S.encode('latin-1')
b'oracle'
>>> S.encode('utf-8')
b'oracle'
>>> S.encode('latin-1')[0]
111
>>> list(S.encode('latin-1'))
[111, 114, 97, 99, 108, 101]
>>>
Кодирование строк символов не ASCII:
Для представления символов можно использовать экранированные последовательности значений байтов и символов Unicode.
Шестнадцатеричные значения 0xdc и 0xd6 представляют коды двух специальных символов, не входящих в диапазон 7-битных символов ASCII:
>>> chr(0xdc)
'Ü'
>>> chr(0xd6)
'Ö'
>>> S = '\xdc\xd6'
>>> S
'ÜÖ'
>>> S = '\u00dc\u00d6'
>>> S
'ÜÖ'
>>> S = chr(0xdc) + chr(0xd6)
>>> S
'ÜÖ'
>>> len(S)
2 # это 2 символа (не число байтов)
>>>
Если попробовать закодировать строки символов не ASCII в последовательность простых байтов, используя кодировку ASCII, мы получим сообщение об ошибке.
Однако, если указать кодировку latin-1, ошибки не будет и каждому символу в строке будет поставлен в соответствие отдельный байт.
При использовании UTF-8 для каждого символа будет выделено по 2 - байта.
>>> S = '\u00dc\u00d6'
>>> S
'ÜÖ'
>>> len(S)
2
>>> S.encode('ascii')
Traceback (most recent call last):
File "
S.encode('ascii')
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
>>> S.encode('latin-1')
b'\xdc\xd6'
>>> S.encode('utf-8')
b'\xc3\x9c\xc3\x96'
>>> len(S.encode('latin-1'))
2
>>> len(S.encode('utf-8'))
4
Можно пойти обратным путем - прочитать последовательность байтов из файла и декодировать их в сторону символов Unicode.
Но лучше в функции open() указать название кодировки, это поможет избежать ошибок, которые могут явиться результатом чтения неполных последовательностей символов, когда чтение выполняется блоками байтов.
>>> B = b'\xdc\xd6'
>>> B
b'\xdc\xd6'
>>> len(B)
2
>>> B.decode('latin-1')
'ÜÖ'
>>> B = b'\xc3\x9c\xc3\x96'
>>> len(B)
4
>>> B.decode('utf-8')
'ÜÖ'
>>> len(B.decode('utf-8'))
2
>>>
Другие способы кодирования строк в Unicode:
>>> S = 'A\u00dcB\U000000d6C'
>>> S
'AÜBÖC'
>>> len(S)
5 # 5 символов
>>> S.encode('latin-1')
b'A\xdcB\xd6C'
>>> len(S.encode('latin-1'))
5 # 5 байтов
>>> S.encode('utf-8')
b'A\xc3\x9cB\xc3\x96C'
>>> len(S.encode('utf-8'))
7 # 7 байтов
>>>
Некоторые кодировки могут иметь существенное различие в кодах символов.
Например кодировка cp500 (EBCDIC), даже символы ASCII кодирует не так как некоторые другие кодировки:
>>> S
'AÜBÖC'
>>> S.encode('cp500')
b'\xc1\xfc\xc2\xec\xc3'
>>> S.encode('cp850')
b'A\x9aB\x99C'
>>> S = 'oracle'
>>> S.encode('latin-1')
b'oracle'
>>> S.encode('utf-8')
b'oracle'
>>> S.encode('cp500')
b'\x96\x99\x81\x83\x93\x85'
>>> S.encode('cp850')
b'oracle'
>>>
С технической точки зрения, можно составлять строки Unicode по частям, используя функцию chr() вместо экранированных шестнадцатеричных значений, но это может оказаться утомительным в случае длинных строк:
>>> S = 'A' + chr(0xdc) + 'B' + chr(0xd6) + 'C'
>>> S
'AÜBÖC'
>>>
В Python допускается в строках типа str кодировать специальные символы с использованием шестнадцатеричных экранированных последовательностей значений байтов и символов Unicode.
Но в строках типа bytes могут применяться только шестнадцатеричные экранированные последовательности значений байтов.
Экранированные последовательности значений символов Unicode в строках типа bytes будут интерпретироваться буквально, а не как экранированные последовательности.
Фактически строки bytes должны декодироваться в строки str, чтобы корректно вывести символы, не являющиеся символами ASCII.
>>> S = 'A\xdcB\xd6C'
>>> S
'AÜBÖC'
>>> S = 'A\u00dcB\U000000d6C'
>>> S
'AÜBÖC' # распознает значения символов
>>> B = b'A\xdcB\xd6C'
>>> B
b'A\xdcB\xd6C' # распознает последовательности байтов
>>> B = b'A\u00dcB\U000000d6C'
>>> B
b'A\\u00dcB\\U000000d6C' # буквально интерпретируются
>>>
>>> B = b'A\xdcB\xd6C'
>>> B
b'A\xdcB\xd6C'
>>> print(B)
b'A\xdcB\xd6C'
>> B.decode('latin-1')
'AÜBÖC'
>>>
При определении литералов bytes допускается использовать символы ASCII, а для байтов со значениями выше 127 - экранированные последовательности шестнадцатеричных значений.
В литералах str допускается использовать любые символы, имеющиеся в исходной кодировке.
( в качестве которой, по умолчанию используется UTF-8, если в исходном файле явно не была объявлена другая кодировка.)
>>> S = 'AÜBÖC'
>>> S
'AÜBÖC'
>>> B = b'A\xdcB\xd6C'
>>> B
b'A\xdcB\xd6C'
>>> B.decode('latin-1')
'AÜBÖC'
>>> S.encode()
b'A\xc3\x9cB\xc3\x96C' # системная кодировка UTF-8
>>> S.encode('UTF-8')
b'A\xc3\x9cB\xc3\x96C'
>>> B.decode() # простые байты не соответствуют кодировке UTF-8
Traceback (most recent call last):
File "
B.decode()
UnicodeDecodeError: 'utf8' codec can't decode byte 0xdc in position 1: invalid continuation byte
>>>
Преобразования между кодировками:
>>> S = 'AÜBÖC'
>>> S
'AÜBÖC'
>>> S.encode()
b'A\xc3\x9cB\xc3\x96C'
>>> T = S.encode('cp500')
>>> T
b'\xc1\xfc\xc2\xec\xc3'
>>> U = T.decode('cp500')
>>> U
'AÜBÖC'
>>> U.encode()
b'A\xc3\x9cB\xc3\x96C'
>>>