Python 3에서 int를 바이트로 변환하는 중
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
이는 0을 반환하는 바이트(int)와 같은 홀수와의 상호작용을 더욱 저하시킵니다.
또, 다음과 같이 합니다.
바이트(int)가 해당 int의 ASCIIfification을 반환하는 것이 훨씬 편리합니다.솔직히 에러라도 이 동작보다 낫습니다.(이 동작을 원한다면 (전혀 없었던) "bytes"와 같이 호출되는 클래스 메서드가 좋습니다.제로(n).
누가 이 행동이 어디서 왔는지 설명해 줄 수 있나요?
python 3.2부터는
>>> (1024).to_bytes(2, byteorder='big')
b'\x04\x00'
https://docs.python.org/3/library/stdtypes.html#int.to_bytes
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)
건데,은 '아까운'이라고 거죠.일반적으로 전화는bytes
「 」 「 」 、 「 」 、 「 」
>>> bytes([3])
b'\x03'
문서에는 다음과 같은 내용이 기재되어 있습니다.bytes
:
>>> help(bytes)
...
bytes(int) -> bytes object of size given by the parameter initialized with null bytes
구조물의 팩을 사용할 수 있습니다.
In [11]: struct.pack(">I", 1)
Out[11]: '\x00\x00\x00\x01'
">"는 바이트 순서(빅 엔디안), "I"는 포맷 문자입니다.따라서 다른 작업을 수행할 경우 다음과 같이 구체적으로 지정할 수 있습니다.
In [12]: struct.pack("<H", 1)
Out[12]: '\x01\x00'
In [13]: struct.pack("B", 1)
Out[13]: '\x01'
이것은 python 2와 python 3 모두에서 동일하게 동작합니다.
주의: 역연산(바이트에서 int)은 언팩으로 실행할 수 있습니다.
Python 3.5+에서는 바이트에 % 인터폴레이션(-printf
style formating)이 도입되었습니다.
>>> b'%d\r\n' % 3
b'3\r\n'
자세한 내용은 PEP 0461 - 바이트 및 번복에 % 형식 추가.
버전에서는 " " " 를 사용할 수 .str
★★★★★★★★★★★★★★★★★」.encode('ascii')
★★★★
>>> s = '%d\r\n' % 3
>>> s.encode('ascii')
b'3\r\n'
주의: 다음 제품과는 다릅니다.
>>> n = 3
>>> n.to_bytes((n.bit_length() + 7) // 8, 'big') or b'\0'
b'\x03'
>>> b'3' == b'\x33' != '\x03'
True
문서에는 다음과 같이 기재되어 있습니다.
bytes(int) -> bytes object of size given by the parameter
initialized with null bytes
순서:
b'3\r\n'
문자 '3'(10진수 51) 문자 '\r'(13) 및 '\n'(10)이다.
따라서 이 방법은 예를 들어 다음과 같이 처리한다.
>>> bytes([51, 13, 10])
b'3\r\n'
>>> bytes('3', 'utf8') + b'\r\n'
b'3\r\n'
>>> n = 3
>>> bytes(str(n), 'ascii') + b'\r\n'
b'3\r\n'
IPython 1.1.0 및 Python 3.2.3에서 테스트 완료
은 3'ASCIIfication'입니다"\x33"
"\x03"
!
이 비단뱀이 하는 이다.str(3)
그러나 바이트는 바이너리 데이터의 배열로 간주되어 문자열로 악용되어서는 안 되기 때문에 완전히 잘못된 것입니다.
것을 하는 가장 쉬운 은 '자신에게'입니다.bytes((3,))
, 더 좋다, 보다.bytes([3])
목록을 초기화하는 것이 훨씬 더 비싸기 때문에 튜플을 사용할 수 있을 때는 목록을 사용하지 마십시오. 는 큰 정수로 할 수 .int.to_bytes(3, "little")
.
바이트를 소정의 길이로 초기화하는 것이 적절하고 가장 유용합니다.이는 바이트가 특정 크기의 메모리를 할당해야 하는 버퍼 유형을 작성할 때 자주 사용되기 때문입니다.어레이를 초기화하거나 파일을 전개할 때 0을 적어 사용하는 경우가 많습니다.
단일 한 방법들의 이 궁금했습니다.[0, 255]
그래서 타이밍 테스트를 몇 가지 하기로 했습니다.
아래의 타이밍과 다양한 값과 설정을 시도하면서 관찰한 일반적인 경향에 따라struct.pack
가장 빠른 것 같으며, 그 다음입니다.int.to_bytes
,bytes
및와 함께, " "str.encode
이데올로기보다제시된 보다 더 많은 변화가 점에 하십시오.int.to_bytes
★★★★★★★★★★★★★★★★★」bytes
속도 경우가 있습니다만, 「스위치 속도 은 「스위치 속도 랭킹」입니다.struct.pack
확실히 가장 빠릅니다.
Windows 의 CPython 3.7 의 결과:
Testing with 63:
bytes_: 100000 loops, best of 5: 3.3 usec per loop
to_bytes: 100000 loops, best of 5: 2.72 usec per loop
struct_pack: 100000 loops, best of 5: 2.32 usec per loop
chr_encode: 50000 loops, best of 5: 3.66 usec per loop
모듈(이름은 ''')int_to_byte.py
"""Functions for converting a single int to a bytes object with that int's value."""
import random
import shlex
import struct
import timeit
def bytes_(i):
"""From Tim Pietzcker's answer:
https://stackoverflow.com/a/21017834/8117067
"""
return bytes([i])
def to_bytes(i):
"""From brunsgaard's answer:
https://stackoverflow.com/a/30375198/8117067
"""
return i.to_bytes(1, byteorder='big')
def struct_pack(i):
"""From Andy Hayden's answer:
https://stackoverflow.com/a/26920966/8117067
"""
return struct.pack('B', i)
# Originally, jfs's answer was considered for testing,
# but the result is not identical to the other methods
# https://stackoverflow.com/a/31761722/8117067
def chr_encode(i):
"""Another method, from Quuxplusone's answer here:
https://codereview.stackexchange.com/a/210789/140921
Similar to g10guang's answer:
https://stackoverflow.com/a/51558790/8117067
"""
return chr(i).encode('latin1')
converters = [bytes_, to_bytes, struct_pack, chr_encode]
def one_byte_equality_test():
"""Test that results are identical for ints in the range [0, 255]."""
for i in range(256):
results = [c(i) for c in converters]
# Test that all results are equal
start = results[0]
if any(start != b for b in results):
raise ValueError(results)
def timing_tests(value=None):
"""Test each of the functions with a random int."""
if value is None:
# random.randint takes more time than int to byte conversion
# so it can't be a part of the timeit call
value = random.randint(0, 255)
print(f'Testing with {value}:')
for c in converters:
print(f'{c.__name__}: ', end='')
# Uses technique borrowed from https://stackoverflow.com/q/19062202/8117067
timeit.main(args=shlex.split(
f"-s 'from int_to_byte import {c.__name__}; value = {value}' " +
f"'{c.__name__}(value)'"
))
int
)long
은 ( )로 할 수 있습니다.bytes
다음 기능을 사용합니다.
import codecs
def int2bytes(i):
hex_value = '{0:x}'.format(i)
# make length of hex_value a multiple of two
hex_value = '0' * (len(hex_value) % 2) + hex_value
return codecs.decode(hex_value, 'hex_codec')
역변환은 다른 방법으로 실행할 수 있습니다.
import codecs
import six # should be installed via 'pip install six'
long = six.integer_types[-1]
def bytes2int(b):
return long(codecs.encode(b, 'hex_codec'), 16)
두 함수는 Python2와 Python3 모두에서 작동합니다.
brunsgaard의 이전 답변은 효율적인 인코딩이지만 부호 없는 정수에서만 작동합니다.이것은 부호 있는 정수와 부호 없는 정수 모두에 대해 작동하도록 구축되어 있습니다.
def int_to_bytes(i: int, *, signed: bool = False) -> bytes:
length = ((i + ((i * signed) < 0)).bit_length() + 7 + signed) // 8
return i.to_bytes(length, byteorder='big', signed=signed)
def bytes_to_int(b: bytes, *, signed: bool = False) -> int:
return int.from_bytes(b, byteorder='big', signed=signed)
# Test unsigned:
for i in range(1025):
assert i == bytes_to_int(int_to_bytes(i))
# Test signed:
for i in range(-1024, 1025):
assert i == bytes_to_int(int_to_bytes(i, signed=True), signed=True)
「」의 ,(i + ((i * signed) < 0)).bit_length()
is 、 「 「 」가 「 」가 됩니다.i.bit_length()
후자는 -128, -32768 등의 비효율적인 인코딩을 초래하기 때문입니다.
Credit: 경미한 비효율성을 고친 CervEd.
, 좋은 방법은 '이진법 표현하다', '이진법 표현하다', '이진법 표현하다', '이진법 표현을 하다', '이진법 표현하다', '이진법 표현하다', '이진법 표현하다', '이진법 표현하다', '이진법 표현하다', '이진법 표현하다'를하는 것입니다.ctypes
.
import ctypes
x = ctypes.c_int(1234)
bytes(x)
없음 및 )을 .c_uint8
,c_int8
,c_unit16
... ), ...)
보다 이전 의 Python에서는 Python 3이 때문에 합니다.bytes
요.str
3.x . Python 3.x 의 . 。bytes
입니다.bytearray
- 역호환성이 없습니다.
시작 바이트 문서:
따라서 컨스트럭터 인수는 bytearray()로 해석된다.
다음으로 byearray docs에서 다음을 수행합니다.
옵션의 source 파라미터를 사용하여 어레이를 초기화할 수 있습니다.
- 정수일 경우 어레이는 해당 크기를 가지며 늘바이트로 초기화됩니다.
이는 2.x(여기서 x >= 6) 동작과는 다릅니다.bytes
말하면str
:
>>> bytes is str
True
2.6 스트링은 3.0의 바이트 유형과 여러 가지 면에서 다릅니다. 특히 컨스트럭터는 완전히 다릅니다.
많은 숫자에 대응하지 않는 대답도 있습니다.
정수를 16진수로 변환한 다음 바이트로 변환합니다.
def int_to_bytes(number):
hrepr = hex(number).replace('0x', '')
if len(hrepr) % 2 == 1:
hrepr = '0' + hrepr
return bytes.fromhex(hrepr)
결과:
>>> int_to_bytes(2**256 - 1)
b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff'
바이트로 변환하기 전에 int를 str로 변환하면 될 것 같아요.그러면 원하는 형식이 생성됩니다.
bytes(str(your_number),'UTF-8') + b'\r\n'
py3.8에서는 효과가 있습니다.
>>> chr(116).encode()
b't'
질문의 대상이 (스트링에 상당하지 않는) 정수 자체를 바이트로 변환하는 방법이라면, 확실한 대답은 다음과 같습니다.
>>> i = 5
>>> i.to_bytes(2, 'big')
b'\x00\x05'
>>> int.from_bytes(i.to_bytes(2, 'big'), byteorder='big')
5
이러한 방법의 상세한 것에 대하여는, 다음의 URL 를 참조해 주세요.
- https://docs.python.org/3.8/library/stdtypes.html#int.to_bytes
- https://docs.python.org/3.8/library/stdtypes.html#int.from_bytes
언급URL : https://stackoverflow.com/questions/21017698/converting-int-to-bytes-in-python-3
'programing' 카테고리의 다른 글
Java에는 경로 결합 방식이 있습니까? (0) | 2022.09.06 |
---|---|
Intelij IDEA, 프로젝트의 모든 코드 포맷 (0) | 2022.09.06 |
Windows에서 MySQL 화면 콘솔을 지우려면 어떻게 해야 합니까? (0) | 2022.09.05 |
e.getMessage()와 e.getLocalizedMessage()의 차이점 (0) | 2022.09.05 |
'-rdynamic'은 정확히 어떤 역할을 하며 언제 필요할까요? (0) | 2022.09.05 |