왜 "bytes(n)"는 n을 이진 표현으로 변환하는 대신 길이 n 바이트 문자열을 생성합니까?
파이썬 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'
설명서를 읽으면서 바이트 변환이 왜 이런 식으로 작동하는지에 대한 포인터를 볼 수 없었습니다.하지만 이번 파이썬 이슈에서 추가에 대한 몇 가지 놀라운 메시지를 발견했습니다.format
바이트 수(Python 3바이트 형식 참조):
http://bugs.python.org/issue3982
이는 바이트(int)가 현재 0을 반환하는 것과 같은 이상한 것과 훨씬 더 나쁘게 상호 작용합니다.
그리고:
바이트(int)가 해당 int의 ASCII화를 반환한다면 훨씬 편리하겠지만, 솔직히 이 동작보다 오류가 더 나을 것입니다.(이 동작을 원했다면 - 저는 결코 그런 적이 없었습니다 - 저는 차라리 "바이트"처럼 호출되는 클래스 메소드가 되고 싶습니다.0(n)".
누가 이 행동이 어디서 왔는지 설명해 줄 수 있나요?
python 3.2에서 다음을 사용할 수 있습니다.
>>> (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)
그것은 그렇게 설계되었습니다 - 그리고 그것은 말이 됩니다 왜냐하면 보통, 당신이 전화를 하기 때문입니다.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 형식)을 도입했습니다.
>>> 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' != b'\x03'
True
설명서에는 다음과 같이 나와 있습니다.
bytes(int) -> bytes object of size given by the parameter
initialized with null bytes
순서:
b'3\r\n'
문자 '3'(소수 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에서 테스트됨
의 ASCII 은 3의 ASCII ."\x33"
것은 아니다."\x03"
!
그것이 파이썬이 하는 일입니다.str(3)
그러나 바이트는 이진 데이터 배열로 간주되어야 하고 문자열로 악용되어서는 안 되므로 바이트에 대해서는 완전히 잘못된 것입니다.
당신이 원하는 것을 성취하는 가장 쉬운 방법은bytes((3,))
어느 쪽이 더 나은 것입니다.bytes([3])
목록을 초기화하는 것이 훨씬 더 비싸기 때문에 튜플을 사용할 수 있을 때는 목록을 사용하지 마십시오.다을사용더여하큰변수있다습니환할정을 하여 더 큰 할 수 .int.to_bytes(3, "little")
.
지정된 길이의 바이트를 초기화하는 것이 가장 유용하며, 이러한 바이트는 지정된 크기의 메모리가 필요한 버퍼 유형을 만드는 데 자주 사용되기 때문입니다.배열을 초기화하거나 파일에 0을 기록하여 파일을 확장할 때 자주 사용합니다.
범위 내 단일 int에 대한 다양한 방법의 성능이 궁금했습니다.[0, 255]
그래서 타이밍 테스트를 해보기로 했습니다.
을 바탕으로, 아의타이과다밍양값구과시한로바성관탕으추일세를인래,struct.pack
가장 빠른 것 같고, 그 뒤를 따릅니다.int.to_bytes
,bytes
와께함과 함께str.encode
(놀랍게도) 가장 느립니다.결과는 표시된 것보다 더 많은 변동을 보여줍니다.int.to_bytes
그리고.bytes
, 테트중에때속때순전도만환지했위를로스,▁ranking만▁during▁sometimes지전▁speed▁but▁switched했,struct.pack
분명히 가장 빠릅니다.
윈도우즈에서 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
(이름은 "Test module)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)'"
))
3 의 Python에서 Python에서 3이라는 의 Python에서 했습니다.bytes
에 대한 가명일 뿐입니다.str
3 Python 3.bytes
는 의불버전다니의 입니다.bytearray
완전히 새로운 유형으로, 이전 버전과 호환되지 않습니다.
바이트 문서에서:
따라서 생성자 인수는 bytearray()로 해석됩니다.
그런 다음 bytearray 문서에서:
옵션인 source 매개 변수는 다음과 같은 몇 가지 방법으로 배열을 초기화하는 데 사용할 수 있습니다.
- 정수인 경우 배열의 크기는 해당 크기이며 null 바이트로 초기화됩니다.
(서 x > =6. 여기서 참고, 이는 2.x (x > = 6) 동작다.bytes
간단히 말하면str
:
>>> bytes is str
True
2.6 str은 3.0의 바이트 유형과 다양한 점에서 다릅니다. 가장 중요한 점은 생성자가 완전히 다르다는 것입니다.
int
(Python2의) )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()
그냥 대신 사용됩니다.i.bit_length()
후자는 -128, -32768 등의 비효율적인 인코딩으로 이어지기 때문입니다.
신용: 사소한 비효율성을 고친 것에 대한 Cerved.
는 표현을처면다려음사이진것좋가다습니장이용는하을리하▁represent▁as다▁best좋▁the▁to니습▁is▁useation,▁with▁binary가이▁you장을 사용하는 것이 가장 좋습니다.ctypes
.
import ctypes
x = ctypes.c_int(1234)
bytes(x)
표현 및 : 특서정부정/표호및수 비트현수없음명서부수::▁you▁represent▁the)을 .c_uint8
,c_int8
,c_unit16
,...).
일부 대답은 큰 숫자와 함께 사용할 수 없습니다.
정수를 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에서 작동합니다.
만약 문제가 정수 자체를 (동일한 문자열이 아닌) 바이트로 변환하는 방법이라면, 강력한 대답은 다음과 같습니다.
>>> i = 5
>>> i.to_bytes(2, 'big')
b'\x00\x05'
>>> int.from_bytes(i.to_bytes(2, 'big'), byteorder='big')
5
이러한 방법에 대한 자세한 내용은 여기를 참조하십시오.
- https://docs.python.org/3.8/library/stdtypes.html#int.to_bytes
- https://docs.python.org/3.8/library/stdtypes.html#int.from_bytes
>>> chr(116).encode()
b't'
언급URL : https://stackoverflow.com/questions/21017698/why-does-bytesn-create-a-length-n-byte-string-instead-of-converting-n-to-a-b
'source' 카테고리의 다른 글
SQL Server 데이터베이스 크기 선택 (0) | 2023.05.06 |
---|---|
iis 7.0에서 .net Framework 4.0 웹 사이트를 실행하는 데 문제가 있습니다. (0) | 2023.05.06 |
모든 키 누르기에서 Angular 2 변경 이벤트 (0) | 2023.05.06 |
셸 스크립트에서 심볼릭 링크를 확인하는 방법 (0) | 2023.05.06 |
빈 커밋을 원격으로 푸시하는 중 (0) | 2023.05.06 |