Python 为什么base64.b64encode()返回字节对象?

Python 为什么base64.b64encode()返回字节对象?,python,python-3.x,unicode,encoding,base64,Python,Python 3.x,Unicode,Encoding,Base64,base64.b64encode()的目的是将二进制数据转换为ASCII安全的“文本”。但是,该方法返回字节类型的对象: >>> import base64 >>> base64.b64encode(b'abc') b'YWJj' 简单地获取输出并对其进行decode()很容易,但我的问题是:base64.b64encode()返回字节而不是str?b64encode()不可能知道您想对其输出做什么 在许多情况下,您可能希望将编码值视为文本,但在许多其他情况

base64.b64encode()
的目的是将二进制数据转换为ASCII安全的“文本”。但是,该方法返回字节类型的对象:

>>> import base64
>>> base64.b64encode(b'abc')
b'YWJj'

简单地获取输出并对其进行
decode()
很容易,但我的问题是:
base64.b64encode()
返回
字节而不是
str

b64encode()
不可能知道您想对其输出做什么

在许多情况下,您可能希望将编码值视为文本,但在许多其他情况下(例如,通过网络发送),您可能希望将其视为字节

因为
b64encode()
无法知道,所以它拒绝猜测。由于输入是
字节
,因此输出保持相同的类型,而不是隐式强制为
str

正如您所指出的,将输出解码为
str
非常简单:

base64.b64encode(b'abc').decode('ascii')
。。。以及明确的结果

另一方面,值得注意的是,尽管自3.3版以来,
base64.b64decode()
(注意:de代码,而不是en代码)已经接受了
str
,但更改是无效的

函数的作用是将二进制数据转换为ASCII安全的“文本”

Python不同意这一点——base64被故意归类为

在Python3中,强制将字节和文本分离并禁止隐式转换是一个设计决策。Python现在对此非常严格,以至于
bytes.encode
甚至不存在,因此
b'abc.encode('base64')
将产生
AttributeError

该语言的观点是bytestring对象已经编码。将字节编码为文本的编解码器不适合这种模式,因为当您想要从字节域转到文本域时,它是一种解码。请注意,
rot13
编码也因为同样的原因被从列表中排除——它不适合Python3范式


还有一个性能参数需要说明:假设Python自动将base64输出(由模块中的C代码生成的ASCII编码二进制表示)解码到文本域中的Python对象中。如果您确实需要字节,您只需通过再次编码为ASCII来撤销解码。这将是一次浪费的往返,一次不必要的双重否定。最好是“选择加入”解码到文本步骤

感谢您的回答,不过我对这个解释有点问题,潜在的输出总是可以用ascii字符串表示,从某种意义上说,ascii字符串是字节对象的子集。我认为您应该以更窄的类型返回结果,如果可能的话,bytes对象可以是任何类型。通常,如果你有一个函数,你将不知道对输出做了什么,你仍然希望以一种有意义的描述性方式返回它,否则所有函数都应该只返回字节,我们应该去掉str类型。换句话说,b64encode()总是知道输出可以表示为str,为什么不返回str呢?请注意,“为什么不返回str呢?”和“为什么不返回bytes对象呢?”之间没有区别。。。它必须选择一些东西,
bytes
被认为是最符合应避免隐含强制的原则的。还要注意的是,
str
绝对不是
bytes
的子集,也不比
窄:前者由多达1114112个不同的代码点组成,而后者只能表示256种不同的状态(可以是整数、字符或其他形式)。ASCII恰好可以表示为两者的一个子集,base64字母表也是如此,但没有内在的理由认为其中一个比另一个更适合。@Code学徒我的思路是“如果您有关于返回数据的其他信息,请提供它”事实上,该方法的输出将始终在ascii安全范围内,作为此类信息。选择称之为“狭隘”可能是一个糟糕的词语选择。否则,我们可以总是返回所有数据的字节对象,因为所有数据都可以表示为原始字节,但这可能不是很有用。我认为“将字节编码为文本的编解码器不适合这种模式,因为当你想从字节域转到文本域时,它是一个解码”为我解释了这一点。因此,孤立地说,它可能没有完美的意义,但从使所有encode()/decode()方法具有统一的输入/输出的精神来看,它是有意义的。我仍然觉得这有点奇怪:)我会说99.99%的时候你想要它作为一个字符串,这应该是默认值。在您关心性能或其他细微差别的情况下,您可以调用另一个函数。从这个意义上讲,base64编码是纯文本的,仅限于ASCII定义,这意味着它的目的是将二进制数据转换为文本表示。我看不出Python实现产生字节的任何原因。字节和文本的分离本身是非常有用的,但在这种情况下,我个人认为,如果在这种情况下,代码不适合这种范式,那么这种范式就根本不应该被应用。