私は 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 の問題で、いくつか意外なメッセージを見つけました( Python 3 のバイト フォーマットformat
も参照)。
これは、bytes(int)がゼロを返すなどの奇妙な動作とさらに悪影響を及ぼします。
そして:
bytes(int) がその int の ASCII 化を返すと、私にとってはずっと便利になりますが、正直なところ、エラーであってもこの動作よりはましです。(この動作が必要な場合は (私は一度もそうしたことはありませんが)、"bytes.zeroes(n)" のように呼び出されるクラスメソッドの方が良いと思います。)
この動作がどこから来るのか誰か説明してくれませんか?
ベストアンサー1
Python 3.2 以降では以下を使用できますto_bytes
:
>>> (1024).to_bytes(2, byteorder='big')
b'\x04\x00'
def int_to_bytes(x: int) -> bytes:
return x.to_bytes((x.bit_length() + 7) // 8, 'big')
def int_from_bytes(xbytes: bytes) -> int:
return int.from_bytes(xbytes, 'big')
したがって、x == int_from_bytes(int_to_bytes(x))
上記のエンコードは符号なし(負でない)整数に対してのみ機能することに注意してください。
符号付き整数の場合、ビット長の計算は少し複雑になります。
def int_to_bytes(number: int) -> bytes:
return number.to_bytes(length=(8 + (number + (number < 0)).bit_length()) // 8, byteorder='big', signed=True)
def int_from_bytes(binary_data: bytes) -> Optional[int]:
return int.from_bytes(binary_data, byteorder='big', signed=True)