Я пытался построить этот объект байтов в Python 3:
b'3\r\n'
поэтому я попробовал очевидное (для меня) и обнаружил странное поведение:
>>> bytes(3) + b'\r\n'
b'\x00\x00\x00\r\n'
По-видимому:
>>> bytes(10)
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
Я не смог увидеть никаких указателей на то, почему преобразование байтов работает таким образом, читая документацию. Однако в этой проблеме Python я обнаружил несколько неожиданных сообщений о добавлении format
в байты (см. Также форматирование байтов в Python 3 ):
http://bugs.python.org/issue3982
Это еще хуже взаимодействует со странностями, такими как bytes (int), теперь возвращая нули
и:
Для меня было бы намного удобнее, если бы bytes (int) возвращал ASCIIfication этого int; но, честно говоря, даже ошибка будет лучше, чем это поведение. (Если бы я хотел такого поведения - которого у меня никогда не было - я бы предпочел, чтобы это был метод класса, вызываемый как «bytes.zeroes (n)».)
Может кто-нибудь объяснить мне, откуда это поведение?
источник
3 .to_bytes
Ответы:
Это так, как это было задумано - и это имеет смысл, потому что обычно вы вызываете
bytes
итерируемое, а не одно целое число:В документах заявить об этом , а также для строке документации
bytes
:источник
bytes
это просто псевдоним дляstr
, что означаетbytes([3])
дает вам'[3]'
.bytes([n])
работает только для int n от 0 до 255. Для всего остального он поднимаетсяValueError
.bytes([3])
он по-прежнему отличается от того, что хотел OP, а именно - значение байта, используемое для кодирования цифры «3» в ASCII, т.е.bytes([51])
то естьb'3'
нетb'\x03'
.bytes(500)
создает строку байтов w / len == 500. Она не создает строку байтов, которая кодирует целое число 500. И я согласен, чтоbytes([500])
это не может работать, поэтому это тоже неправильный ответ. Вероятно, правильный ответint.to_bytes()
для версий> = 3.1.С Python 3.2 вы можете сделать
https://docs.python.org/3/library/stdtypes.html#int.to_bytes
Соответственно
x == int_from_bytes(int_to_bytes(x))
. Обратите внимание, что эта кодировка работает только для беззнаковых (неотрицательных) целых чисел.источник
b"3"
от3
, как спрашивает вопрос. (Это дастb"\x03"
.)Вы можете использовать пакет struct :
«>» - это порядок байтов (big-endian), а «I» - символ формата . Так что вы можете быть конкретны, если хотите сделать что-то еще:
Это работает одинаково как на python 2, так и на python 3 .
Примечание: обратная операция (bytes to int) может быть выполнена с помощью unpack .
источник
I
,H
иB
работают до2**k - 1
где к 32, 16 и 8 соответственно. Для больших входов они повышаютstruct.error
.b'3\r\n'
, то есть байтовую строку, содержащую символ ASCII "3", а не символ ASCII "\ x03"\x03
, и решение , если вы просто хотитеb'3'
тривиальны. Причина, на которую ссылается АББ, гораздо более вероятна ... или, по крайней мере, понятна.bytes([x])
и(x).to_bytes()
методы в Python 3.5. Это было неожиданно.В Python 3.5+ введена% -интерполяция (-стилевое
printf
форматирование) для байтов :См. PEP 0461 - Добавление% форматирования в байты и байтовый массив .
На более ранних версиях вы могли использовать
str
и.encode('ascii')
результат:Примечание: это отличается от того, что
int.to_bytes
производит :источник
Документация гласит:
Последовательность:
Это символ '3' (десятичный 51), символ '\ r' (13) и '\ n' (10).
Поэтому способ будет относиться к нему как таковой, например:
Протестировано на IPython 1.1.0 и Python 3.2.3
источник
bytes(str(n), 'ascii') + b'\r\n'
илиstr(n).encode('ascii') + b'\r\n'
. Спасибо! :)"{}\r\n".format(n).encode()
я не думаю, что использование кодировки utf8 по умолчанию приносит вредASCIIfication 3
"\x33"
не является"\x03"
!Это то, что делает Python,
str(3)
но это будет совершенно неправильно для байтов, поскольку они должны рассматриваться как массивы двоичных данных и не должны использоваться как строки.Самый простой способ достичь желаемого -
bytes((3,))
лучше, чемbytes([3])
инициализация списка, это намного дороже, поэтому никогда не используйте списки, когда вы можете использовать кортежи. Вы можете конвертировать большие целые числа, используяint.to_bytes(3, "little")
.Инициализация байтов с заданной длиной имеет смысл и является наиболее полезной, так как они часто используются для создания некоторого типа буфера, для которого вам требуется выделенная память определенного размера. Я часто использую это при инициализации массивов или расширении файла путем записи в него нулей.
источник
b'3'
естьb'\x33'
, а неb'\x32'
. (б)(3)
не кортеж - вы должны добавить запятую. (c) Сценарий инициализации последовательности с нулями не применяется кbytes
объектам, поскольку они неизменны (bytearray
хотя для s это имеет смысл ).bytes
иbytearray
, я думаю, это в основном вопрос последовательности. Но это также полезно, если вы хотите поместить некоторые нули в буфер или файл, и в этом случае он используется только как источник данных.int
(включая Python2long
) можно преобразовать вbytes
следующую функцию:Обратное преобразование может быть сделано другим:
Обе функции работают как на Python2, так и на Python3.
источник
Мне было любопытно о производительности различных методов для одного int в диапазоне
[0, 255]
, поэтому я решил провести некоторые временные тесты.На основании приведенных ниже тайминги, а также от общей тенденции я наблюдал от попыток много различных значений и конфигураций,
struct.pack
кажется, самым быстрым, а затемint.to_bytes
,bytes
и сstr.encode
(неудивительно) является самым медленным. Обратите внимание, что результаты показывают несколько больше вариаций, чем представлено,int.to_bytes
иbytes
иногда переключаются ранжирование скорости во время тестирования, ноstruct.pack
, очевидно, является самым быстрым.Результаты в CPython 3.7 для Windows:
Тестовый модуль (названный
int_to_byte.py
):источник
[0, 255]
. Я предполагаю, что под «неправильным индикатором» вы подразумеваете, что мои измерения не были достаточно общими, чтобы соответствовать большинству ситуаций? Или моя методология измерения была плохой? Если последнее, мне было бы интересно услышать, что вы хотите сказать, но если первое, я никогда не утверждал, что мои измерения были общими для всех вариантов использования. В моей (возможно, нишевой) ситуации я имею дело только с целыми рядами в диапазоне[0, 255]
, и именно к этой аудитории я собирался обратиться с этим ответом. Был ли мой ответ неясным? Я могу отредактировать это для ясности ...bytes((i,))
вместо того,bytes([i])
потому что список более сложный, использует больше памяти и занимает много времени для инициализации. В этом случае даром.Хотя предыдущий ответ brunsgaard является эффективной кодировкой, он работает только для целых чисел без знака. Это основано на том, что оно работает для целых чисел как со знаком, так и без знака.
Для кодера
(i + ((i * signed) < 0)).bit_length()
используется, а не толькоi.bit_length()
потому, что последний приводит к неэффективному кодированию -128, -32768 и т. Д.Кредит: CervEd для устранения незначительной неэффективности.
источник
int_to_bytes(-128, signed=True) == (-128).to_bytes(1, byteorder="big", signed=True)
этоFalse
-128
, и-32768
т.д.(i+(signed*i<0)).bit_length()
Поведение происходит из-за того, что в Python до версии 3
bytes
был просто псевдоним дляstr
. В Python3.xbytes
есть неизменяемая версияbytearray
- совершенно новый тип, не обратно совместимый.источник
Из байтов документов :
Затем из документа bytearray :
Обратите внимание, что отличается от поведения 2.x (где x> = 6), где
bytes
простоstr
:ОПТОСОЗ 3112 :
источник
Некоторые ответы не работают с большими числами.
Преобразовать целое число в шестнадцатеричное представление, затем преобразовать его в байты:
Результат:
источник
int.to_bytes
работает с любым целым числом.Если вопрос заключается в том, как преобразовать само целое число (не его строковый эквивалент) в байты, я думаю, надежный ответ:
Больше информации об этих методах здесь:
источник