base64.b64encode()
的目的是将二进制数据转换为 ASCII 安全的“文本”。不过,该方法返回一种字节类型的对象:
>>> import base64
>>> base64.b64encode(b'abc')
b'YWJj'
简单来说,我们可以使用 decode()
方法对文本进行解码,但我的问题是:为什么 base64.b64encode()
返回的是 bytes
而不是 str
?
base64.b64encode()
的目的是将二进制数据转换为 ASCII 安全的“文本”。不过,该方法返回一种字节类型的对象:
>>> import base64
>>> base64.b64encode(b'abc')
b'YWJj'
简单来说,我们可以使用 decode()
方法对文本进行解码,但我的问题是:为什么 base64.b64encode()
返回的是 bytes
而不是 str
?
b64encode()
不知道你想如何处理它的输出。
虽然在很多情况下你可能会把编码后的值看作文本,但在其他情况下,例如发送到网络上时,你可能需要将其视为字节。
b64encode()
无法猜测,因此它拒绝尝试。由于输入是 bytes
,所以输出保持相同类型,而不会被隐式强制转换为 str
。
正如你指出的那样,将输出解码为 str
是简单的:
base64.b64encode(b'abc').decode('ascii')
同时还需明确结果。
值得一提的是,尽管base64.b64decode()
(注意:decode而不是encode)自3.3版本以来已经接受了str
,但这个更改曾经引起争议。
base64.b64encode()函数的目的是将二进制数据转换为ASCII安全的“文本”。
Python不赞同这一点 - base64已经被有意地归类为二进制转换。
在Python 3中,强制分离字节和文本并禁止隐式转换是一项设计决策。Python现在对此非常严格,以至于bytes.encode
甚至不存在,因此b'abc'.encode('base64')
会引发一个AttributeError
。
语言的观点是,一个字节串对象已经被编码了。将字节转换为文本的编解码器不符合这种范式,因为当你想从字节域转换到文本域时,需要进行解码。请注意,由于相同的原因,rot13
编码也被从标准编码列表中驱逐出去了 - 它不能很好地适应Python 3的范式。
还可以提出一个性能论点:假设Python自动处理了base64输出的解码,这是C代码从binascii
模块产生的ASCII编码的二进制表示,转换为文本域中的Python对象。如果你实际上需要的是字节,那么你只需要通过再次进行ASCII编码来撤销解码即可。这将是一个浪费时间的往返操作,一个不必要的双重否定。最好选择“选择加入”解码到文本步骤。
bytes
被认为是最符合隐式强制转换应该被避免的原则的。 - Zero Piraeusstr
绝对不是bytes
的子集或者比bytes
更窄:前者由多达 1,114,112 种不同的代码点组成,而后者只能表示 256 种不同的状态(可以是整数、字符或其他)。ASCII 恰好可以用两者的一个子集来表示,base64 字母表也是如此,但没有固有的理由认为其中一个比另一个更符合自然。 - Zero Piraeus