Представлять шестнадцатеричную форму целого числа > 31 в виде ‘x020’

#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]) , чтобы получить байт определенного значения.