Following system colour scheme - Python 增强提案 Selected dark colour scheme - Python 增强提案 Selected light colour scheme - Python 增强提案

Python 增强提案

PEP 467 – 二进制序列的次要API改进

作者:
Alyssa Coghlan <ncoghlan at gmail.com>, Ethan Furman <ethan at stoneleaf.us>
讨论至:
Discourse 帖子
状态:
草案
类型:
标准跟踪
创建日期:
2014年3月30日
Python 版本:
3.15
发布历史:
2014年3月30日, 2014年8月15日, 2014年8月16日, 2016年6月7日, 2016年9月1日, 2021年4月13日, 2021年11月3日, 2023年12月27日

目录

摘要

本PEP提议对 bytesbytearray 类型的API进行微调,以便更轻松地完全在二进制域中操作

  • 添加 fromsize 替代构造函数
  • 添加 fromint 替代构造函数
  • 添加 getbyte 字节检索方法
  • 添加 iterbytes 替代迭代器

最后两个 (getbyteiterbytes) 也将添加到 memoryview

基本原理

在Python 3语言规范的初始开发阶段,用于任意二进制数据的核心 bytes 类型最初是现在称为 bytearray 的可变类型。在Python 3系列的发展过程中,Python中在二进制域中操作的其他方面也得到了发展,例如 PEP 461

动机

随着Python 3以及 strbytes 的分离,编程中一个虽小但重要的领域变得稍微困难,并且痛苦得多——线材格式协议。

这个编程领域的特点是二进制数据和ASCII兼容的文本片段(即ASCII编码的文本)的混合。新构造函数、方法和迭代器的添加将有助于编写新的线材格式代码以及更新现有代码。

常见的用例包括 dbfpdf 文件格式、email 格式以及 FTPHTTP 通信等。

提案

添加显式的“计数和字节初始化序列”构造函数

为了替代不鼓励的从基本构造函数创建零填充的 bytes-like 对象行为(即 bytes(1) –> b'\x00'),本PEP提议在 bytesbytearray 上添加一个显式的 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 将表现得与当前构造函数在传递单个整数时相同,同时在需要时允许非零填充值。

添加显式的“单字节”构造函数

作为文本 chr 函数的二进制对应物,本PEP提议在 bytesbytearray 上添加一个显式的 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提议 bytesbytearraymemoryview 获得 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提议 bytesbytearraymemoryview 获得一个优化的 iterbytes 方法,该方法生成长度为1的 bytes 对象而不是整数。

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')

设计讨论

为什么不依赖序列重复来创建零初始化的序列?

零初始化序列可以通过序列重复创建。

>>> 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) 的提案行为相同。将这两种行为作为单独的类方法提供可以避免这种歧义。

当前的权宜之计

将近十年后,对于字节迭代的最佳权宜之计似乎没有达成共识,正如 从字节对象中获取单字节字节对象 所证明的。

省略最初提议的内置函数

提交给指导委员会时,本PEP提议引入一个 bchr 内置函数(与 bytes.fromint 具有相同的行为),以不同的命名方案(ord/bchr/chr)重新创建 Python 2 中的 ord/chr/unichr 三重奏。

SC表示他们不认为这种功能的使用频率足以证明提供两种相同功能的实现方式,尤其其中一种是新的内置函数。因此,提案的该部分被删除,因为它与 bytes.fromint 替代构造函数是冗余的。

经常使用此方法的开发人员可以选择定义自己的 bchr = bytes.fromint 别名。

参考资料


来源: https://github.com/python/peps/blob/main/peps/pep-0467.rst

最后修改: 2025-05-06 21:00:16 GMT