Вы правы - это шестнадцатеричная нотация.
В байтах буквальных, любые байты, который не может быть представлены в виде печатной ASCII символа (или один из стандартных ускользает \n
, \t
или \r
) представляются в виде \xNN
, где NN является 2-значным шестнадцатеричным представлением байт.
Что вас смущает, так это то, что вы ошибаетесь, например. \xf1Y
для одной последовательности бежать, когда на самом деле он представляет собой два отдельных байт:
>>> len(b'\xf1Y')
2
>>> [bytes([b]) for b in b'\xf1Y']
[b'\xf1', b'Y']
Если перебрать объект байт, вы получите целые значения байт обратно:
>>> list(b'vy\xe9\xb5\xa2\xba\xf1Y\xe8\xe1fl\x1d\x87\xacC')
[118, 121, 233, 181, 162, 186, 241, 89, 232, 225, 102, 108, 29, 135, 172, 67]
>>> bytes([118])
b'v'
>>> bytes([121])
b'y'
>>> bytes([233])
b'\xe9'
Документация для escape sequences in Python string and bytes objects содержит немного больше информации об управляющих последовательностях, которые Python понимает (хотя те, которые указаны выше, являются единственными, которые используются для представления объектов байтов).
Спасибо! Да, это меня путало. Я не знал, что он смешивает литералы с буквальными символами рядом с шестнадцатеричными кодами/x__. –