为什么我们需要str类型?为什么不只是字节串?

Hat*_*sut 5 python unicode python-3.x

Python3有unicode字符串(str)和bytes.我们已经有了bytestring文字和方法.为什么我们需要两种不同的类型,而不仅仅是各种编码的字节串?

Ray*_*oal 9

你的问题的答案取决于"需要"一词的含义.

我们当然不需要这种str类型,我们可以使用我们也可以在没有它的情况下计算的类型来计算所有类型(正如您从措辞良好的问题中得知的那样).

但我们也可以从方便的角度理解"需要".有sqrt功能不是很好吗?或logexpsin?你可以自己写这些,但为什么要这么麻烦?标准库设计器将添加有用且方便的功能.

语言本身也是如此.我们"需要"一段时间的循环吗?不是,我们可以使用尾递归函数.我们"需要"列表理解吗?Python中的大量事物并不是原始的.就此而言,我们"需要"高级语言.John von Neumann自己曾经问过"为什么你想要的不仅仅是机器语言?"

str和相同bytes.这种类型str虽然不是必需的,但它是一种不错的,省时的,方便的.它为我们提供了一个接口作为一系列字符,这样我们就可以逐个字符地操作文本而不需要:

  • 我们必须自己编写所有的编码和解码逻辑,或者
  • 使用多组迭代器膨胀字符串接口,例如each_byteeach_char.

正如您所怀疑的那样,我们可以使用一种类型来暴露字节序列和字符序列(正如Ruby的String类所做的那样).Python设计者希望这些用法分成两种不同的类型.您可以非常轻松地将一种类型的对象转换为另一种对象.通过有两种类型,他们说关注点(和用法点)的分离比内置类型更少更重要.Ruby做出了不同的选择.

TL; DR这是语言设计中的偏好问题:通过不同类型而不是相同类型的不同方法分离关注点.


Ale*_*agh 6

因为字节不应被视为字符串,并且字符串不应被视为字节.无论这对全新开发者有多刺耳,Python3都能做到这一点.

在Python 2.6中,如果我从文件中读取数据,并且我传递了"r"标志,则默认情况下将在当前语言环境中读取文本,这将是一个字符串,而传递"rb"标志将创建一个系列的字节数.索引数据是完全不同的,采用a的方法str可能不确定我是使用字节还是str.这变得更糟,因为对于ASCII数据,这两者通常是同义的,这意味着在遇到非ASCII字符时,在简单测试用例或英语语言环境中工作的代码将失败.

因此,有意识地努力确保字节和字符串不相同:一个是"哑字节"序列,另一个是Unicode字符串,其中数据的最佳编码保留O(1)索引(ASCII, UCS-2,或UTF-32,取决于所使用的数据,我相信).

在Python 2中,Unicode字符串用于消除"哑字节"中的文本歧义,但是,str许多用户将其视为文本.

或者,引用仁慈的独裁者:

Python的当前字符串对象已重载.它们用于保存字符序列和字节序列.这种超载的目的会导致混乱和错误.在Python的未来版本中,字符串对象将用于保存字符数据.bytes对象将履行字节容器的角色.最终,unicode类型将重命名为str,旧的str类型将被删除.

tl; dr版本 强制分离bytesstr迫使编码人员意识到他们的差异,对短期的不满,但更好的代码是长期的.经过多年的经验,这是一种有意识的选择:迫使您立即意识到这种差异将在以后的调试器中节省您的时间.

  • 一切都非常真实而且很好.不过,我总是发现,将字节和字符分开是美妙而恰当的,解放和欢迎,而且根本不会"烦人".令人讨厌的是这两个概念的混淆.Python 2试图将这些概念混为一谈,导致了对"ASCII解码错误:序数不在范围内(128)"的巨大烦恼,因此它是Python 2,而不是3,这很烦人.Python 2必须死,越快越好.咆哮结束.:) (2认同)
  • 啊,真的!因此,我们需要进行大规模的文化转变,以便新开发人员没有理由_期望_字节是字符。也许问题出在那些先学C的人身上?如果您从 Python 3 开始,您应该对其中的差异感到非常满意。 (2认同)