PEP 467 – 바이너리 시퀀스를 위한 사소한 API 개선
- Author:
- Alyssa Coghlan <ncoghlan at gmail.com>, Ethan Furman <ethan at stoneleaf.us>
- Discussions-To:
- Discourse thread
- Status:
- Draft
- Type:
- Standards Track
- Created:
- 30-Mar-2014
- Python-Version:
- 3.15
- Post-History:
- 30-Mar-2014, 15-Aug-2014, 16-Aug-2014, 07-Jun-2016, 01-Sep-2016, 13-Apr-2021, 03-Nov-2021, 27-Dec-2023
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
이 PEP는 전적으로 바이너리 영역에서 작업하기 쉽도록 bytes 및 bytearray 타입의 API를 소폭 조정할 것을 제안합니다.
fromsize대체 생성자 추가fromint대체 생성자 추가- 바이트 검색 메서드
getbyte추가 iterbytes대체 이터레이터 추가
마지막 두 메서드(getbyte 및 iterbytes)도 memoryview에 추가합니다.
근거
Python 3 언어 사양을 처음 개발할 당시 임의의 바이너리 데이터를 위한 핵심 bytes 타입은 현재 bytearray라고 부르는 변경 가능한 타입으로 시작했습니다. Python에서 바이너리 영역을 다루는 다른 측면도 Python 3 시리즈가 진행되는 동안 발전했으며, 그 예로 PEP 461을 들 수 있습니다.
동기
Python 3과 str 및 bytes의 분리로 인해 작지만 중요한 프로그래밍 영역 하나가 약간 더 어려워졌으며, 특히 와이어 형식 프로토콜은 훨씬 더 고통스러워졌습니다.
이 프로그래밍 영역은 바이너리 데이터와 ASCII 호환 텍스트 세그먼트(즉, ASCII로 인코딩된 텍스트)가 혼합되어 있다는 특징이 있습니다. 새로운 생성자, 메서드 및 이터레이터를 추가하면 새로운 와이어 형식 코드를 작성하고 기존 코드를 업데이트하는 데 모두 도움이 됩니다.
일반적인 사용 사례로는 dbf 및 pdf 파일 형식, email 형식, FTP 및 HTTP 통신 등이 있으며, 이 밖에도 많습니다.
제안
명시적인 “개수 및 바이트로 초기화된 시퀀스” 생성자 추가
기본 생성자에서 0으로 채워진 bytes와 유사한 객체를 생성하는 권장되지 않는 동작(즉, bytes(1) –> b'\x00')을 대체하기 위해, 이 PEP는 bytes 및 bytearray 모두에 클래스 메서드로 명시적인 fromsize 대체 생성자를 추가할 것을 제안합니다. 첫 번째 인자는 개수이고 두 번째 인자는 사용할 채움 바이트이며(기본값은 \x00),:
>>> bytes.fromsize(3)
b'\x00\x00\x00'
>>> bytearray.fromsize(3)
bytearray(b'\x00\x00\x00')
>>> bytes.fromsize(5, b'\x0a')
b'\x0a\x0a\x0a\x0a\x0a'
>>> bytearray.fromsize(5, fill=b'\x0a')
bytearray(b'\x0a\x0a\x0a\x0a\x0a')
fromsize는 단일 정수를 전달했을 때 현재 생성자가 동작하는 방식과 동일하게 동작하면서, 필요할 때 0이 아닌 채움 값을 사용할 수 있도록 합니다.
명시적인 “단일 바이트” 생성자 추가
텍스트용 chr 함수에 대응하는 바이너리 기능으로서, 이 PEP는 bytes 및 bytearray 모두에 클래스 메서드로 명시적인 fromint 대체 생성자를 추가할 것을 제안합니다.:
>>> bytes.fromint(65)
b'A'
>>> bytearray.fromint(65)
bytearray(b'A')
이 메서드는 0 이상 255 이하의 정수만 허용합니다.:
>>> bytes.fromint(512)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: integer must be in range(0, 256)
>>> bytes.fromint(1.0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'float' object cannot be interpreted as an integer
ord 내장 함수의 문서를 업데이트하여, 바이너리 데이터에서는 bytes.fromint가 주된 역연산이고 텍스트 데이터에서는 chr가 역연산이며 bytearray.fromint도 존재한다는 점을 명시적으로 기술합니다.
동작 측면에서 bytes.fromint(x)는 현재의 bytes([x])와 동일하며(bytearray도 마찬가지입니다) 새로운 표기법은 특히 바이너리 시퀀스 타입의 인덱싱 연산과 함께 사용할 때 더 쉽게 발견하고 읽을 수 있을 것으로 예상됩니다.
별도의 메서드로 제공되는 새로운 표기법은 map과 같은 고차 함수와 함께 사용할 때도 더 잘 작동합니다.
이러한 새 메서드는 기존 int.to_bytes 변환 메서드와 동일한 수준의 일반 정수 지원을 의도적으로 제공하지 않습니다. 기존 메서드는 임의로 큰 정수를 임의로 긴 바이트 객체로 변환할 수 있습니다. 단일 바이트에 들어맞는 양의 정수만 허용하도록 제한하면 바이트 순서 정보가 필요하지 않으며 음수를 처리할 필요도 없습니다. 새로운 메서드의 문서에서는 임의의 정수를 처리해야 하는 사용 사례를 위해 독자에게 int.to_bytes를 참조하도록 안내합니다.
단일 바이트를 가져오기 위한 “getbyte” 메서드 추가
이 PEP는 bytes, bytearray 및 memoryview에 메서드 getbyte를 추가하며, 이 메서드는 항상 bytes를 반환합니다.:
>>> b'abc'.getbyte(0)
b'a'
존재하지 않는 인덱스를 요청하면 IndexError가 발생합니다.:
>>> b'abc'.getbyte(9)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: index out of range
bytes 객체를 생성하는 최적화된 이터레이터 메서드의 추가
이 PEP에서는 bytes, bytearray 및 memoryview에 정수 대신 길이가 1인 bytes 객체를 생성하는 최적화된 iterbytes 메서드를 추가할 것을 제안합니다.:
for x in data.iterbytes():
# x is a length 1 ``bytes`` object, rather than an integer
예를 들어:
>>> tuple(b"ABC".iterbytes())
(b'A', b'B', b'C')
설계 논의
0으로 초기화된 시퀀스를 생성하는 데 시퀀스 반복에 의존하지 않는 이유는 무엇입니까?
시퀀스 반복을 통해 0으로 초기화된 시퀀스를 생성할 수 있습니다.:
>>> b'\x00' * 3
b'\x00\x00\x00'
>>> bytearray(b'\x00') * 3
bytearray(b'\x00\x00\x00')
그러나 bytearray 형식이 처음 설계되었을 때에도 상황은 동일했으며, 형식 생성자에서 이를 명시적으로 지원하기로 결정했습니다. 이후 불변 bytes 형식이 PEP 3137에서 도입되면서 해당 기능을 상속했습니다.
이 PEP에서는 원래의 설계 결정을 다시 검토하는 것이 아니라 표기만 변경합니다. 사용자가 바이너리 시퀀스 생성자의 현재 동작을 때때로 혼란스럽게 여기기 때문입니다. 특히 bytes(x)(여기서 x는 정수임)가 이 PEP에서 제안하는 bytes.fromint(x)와 같이 동작해야 한다고 볼 만한 합리적인 근거가 있습니다. 두 동작을 별도의 클래스 메서드로 제공하면 이러한 모호성을 피할 수 있습니다.
현재의 우회 방법
거의 10년이 지난 후에도 Get single-byte bytes objects from bytes objects에서 드러나듯이 바이트 반복을 위한 최선의 우회 방법에 대한 합의가 이루어지지 않은 것으로 보입니다.
원래 제안된 내장 함수의 제외
Steering Council에 제출되었을 때 이 PEP에서는 bytes.fromint와 동일한 동작을 하는 bchr 내장 함수의 도입을 제안했습니다. 이는 Python 2의 ord/chr/unichr 세트를 다른 명명 방식인 ord/bchr/chr로 재현하는 것이었습니다.
SC는 동일한 작업을 수행하는 두 가지 방법을 제공하는 것을 정당화할 만큼 이 기능이 자주 필요하다고 생각하지 않는다고 밝혔으며, 특히 그중 하나가 새로운 내장 함수인 경우에는 더욱 그러했습니다. 따라서 제안의 해당 부분은 bytes.fromint대체 생성자와 중복되므로 삭제되었습니다.
이 메서드를 자주 사용하는 개발자는 대신 자체적으로 bchr = bytes.fromint별칭을 정의할 수 있습니다.
참고 자료
Copyright
This document has been placed in the public domain.