Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python 개선 제안 한국어 번역

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

Table of Contents

번역·라이선스 안내

이 비공식 한국어 번역은 원문 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 같은 고차 함수와도 더 잘 어울립니다.

이 새 메서드들은 임의로 큰 정수를 임의 길이의 bytes 객체로 변환할 수 있는 기존 int.to_bytes 변환 메서드와 같은 수준의 일반적인 정수 지원을 의도적으로 제공하지 않습니다. 단일 바이트에 들어가는 양의 정수만 받도록 제한하면 바이트 순서 정보가 필요 없고, 음수를 처리할 필요도 없습니다. 새 메서드의 문서는 임의의 정수를 처리해야 하는 사용 사례에 대해 독자가 int.to_bytes를 참조하도록 안내합니다.

단일 바이트를 조회하는 “getbyte” 메서드 추가

이 PEP는 bytes, bytearray, memoryview에 항상 bytes를 반환하는 getbyte 메서드를 추가할 것을 제안합니다:

>>> 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는 bchr 내장 함수(bytes.fromint와 동일하게 동작)의 도입을 제안하여, Python 2의 ord/chr/unichr 3종 세트를 다른 명명 체계(ord/bchr/chr)로 재현하고자 했습니다.

운영 위원회는 같은 일을 하는 두 가지 방법을 제공하는 것을 정당화할 만큼 이 기능이 자주 필요하지는 않다고 판단했으며, 특히 그 방법 중 하나가 새로운 내장 함수인 경우에는 더욱 그렇다는 의견을 밝혔습니다. 따라서 제안의 해당 부분은 bytes.fromint 대체 생성자와 중복된다는 이유로 제외되었습니다.

이 메서드를 자주 사용하는 개발자는 그 대신 자신만의 bchr = bytes.fromint 별칭을 정의할 수 있습니다.

참고 문헌