#python #character-encoding #hex
#python #кодировка символов #шестнадцатеричное
Вопрос:
Я пытаюсь написать функцию Python, которая выполняет кодировку строки UTF-8 в байтах. Учитывая, "abbcccddddaaaaaa"
что это вернет b'x01ax02bx03cx04dx06a'
.
Я почти решил эту проблему, за исключением того, что я застрял с преобразованием моей длины пробега (целое число) в шестнадцатеричный в желаемом формате, который является символьным ( x
), а не числовым ( 0x
).
Мне нужна функция, которая будет принимать десятичное число и возвращать его в шестнадцатеричном виде в форме 'x<hex form>'
. Например, это поведение chr()
для чисел до 31:
chr(1)
> 'x01'
chr(31)
> 'x1f'
Однако выше 31 он печатает символ.
Вещи, которые не работают:
hex(32)
> '0x20'
re.sub('0', '', hex(32), count=1)
> SyntaxError: EOL while scanning string literal
re.sub('0', '\', hex(32), count=1)
> error: bad escape (end of pattern) at position 0
re.sub('0', r'\', hex(32), count=1)
> '\x20'
Желаемый результат:
my_func(32)
> 'x20'
Ответ №1:
Используйте строку формата:
>>> def my_func(n):
... return f'\x{n:02x}'
...
>>> print(my_func(32))
x20
>>> print(''.join([my_func(n) for n in s]))
x00x01x02x03x04x05x06x07x08x09x0ax0bx0cx0dx0ex0fx10x11x12x13x14x15x16x17x18x19x1ax1bx1cx1dx1ex1fx20x21x22x23x24x25x26x27x28x29x2ax2bx2cx2dx2ex2fx30x31x32x33x34x35x36x37x38x39x3ax3bx3cx3dx3ex3fx40x41x42x43x44x45x46x47x48x49x4ax4bx4cx4dx4ex4fx50x51x52x53x54x55x56x57x58x59x5ax5bx5cx5dx5ex5fx60x61x62x63x64x65x66x67x68x69x6ax6bx6cx6dx6ex6fx70x71x72x73x74x75x76x77x78x79x7ax7bx7cx7dx7ex7fx80x81x82x83x84x85x86x87x88x89x8ax8bx8cx8dx8ex8fx90x91x92x93x94x95x96x97x98x99x9ax9bx9cx9dx9ex9fxa0xa1xa2xa3xa4xa5xa6xa7xa8xa9xaaxabxacxadxaexafxb0xb1xb2xb3xb4xb5xb6xb7xb8xb9xbaxbbxbcxbdxbexbfxc0xc1xc2xc3xc4xc5xc6xc7xc8xc9xcaxcbxccxcdxcexcfxd0xd1xd2xd3xd4xd5xd6xd7xd8xd9xdaxdbxdcxddxdexdfxe0xe1xe2xe3xe4xe5xe6xe7xe8xe9xeaxebxecxedxeexefxf0xf1xf2xf3xf4xf5xf6xf7xf8xf9xfaxfbxfcxfdxfexff
Если вы хотите переопределить отображение строки байтов, вы могли бы использовать:
>>> class Bytes(bytes):
... def __repr__(self):
... return "b'" ''.join([f'\x{n:02x}' for n in self]) "'"
...
>>> s = b'abc'
>>> s
b'abc'
>>> Bytes(s)
b'x61x62x63'
Или просто использовать функцию:
>>> def display(s):
... print("b'" ''.join([f'\x{n:02x}' for n in s]) "'")
...
>>> display(s)
b'x61x62x63'
Комментарии:
1. Это работает для печати, но я думаю, что я хочу «обмануть» Python, заставив его думать, что это символ, чтобы он изначально использовал
x
префикс поверх0x
, поэтому он хранится внутри какx
, а не\x
. Возможно ли это?2. Нет «сохраненного внутреннего как xnn». Байт есть байт. По умолчанию строка байтов отображается как escape-коды для байтов, отличных от ASCII и непечатаемых, и фактический символ ASCII для байтов ASCII, доступных для печати. Вы хотите сгенерировать собственное отображение строки байтов.
3. Хорошо, я понимаю. Тем не менее, я не уверен, как выразить проблему, но я добавил контекст к вопросу. По сути, мне нужно преобразовать
"abbcccddddaaaaaa"
вb'x01ax02bx03cx04dx06a'
(неb'\x01a\x02b\x03c\x04d\x06a'
).4. Это вопрос кодирования.
bytes('ÿ', 'latin1')
будет выводитьb'xff'
, ноbytes('a','latin1')
все равно будет печататьb'a'
.latin1
кодировка отображает Unicode от U 0000 до U 00FF (символы латинской 1) в байты 0x00-0xff.5. Вы также можете просто сделать
bytes([n])
, чтобы получить байт определенного значения.