PEP 349 – 允许 str() 返回 unicode 字符串
- 作者:
- Neil Schemenauer <nas at arctrix.com>
- 状态:
- 已拒绝
- 类型:
- 标准跟踪
- 创建日期:
- 2005年8月2日
- Python 版本:
- 2.5
- 发布历史:
- 2005年8月6日
- 决议:
- Python-Dev 消息
摘要
本 PEP 提议修改内置函数 str(),使其能够返回 unicode 字符串。这一改变将使编写同时适用于两种字符串类型的代码变得更容易,并且还会使一些现有代码能够处理 unicode 字符串。C 函数 PyObject_Str() 将保持不变,取而代之的是添加函数 PyString_New()。
基本原理
Python 已经有了一段时间的 Unicode 字符串类型,但其使用尚未普及。大量的 Python 代码假定字符串数据表示为 str 实例。Python 的长期计划是逐步淘汰 str 类型,并对所有字符串数据使用 unicode。显然,必须提供平稳的迁移路径。
我们需要升级为 str 实例编写的现有库,使其能够在全 unicode 字符串世界中运行。在所有必要的库都具备此能力之前,我们无法切换到全 unicode 世界。一次性升级所有库似乎不可行。一个更现实的策略是单独使库能够操作 unicode 字符串,同时保留其当前的全部 str 环境行为。
首先,我们需要能够编写接受 unicode 实例的代码,而无需尝试将其强制转换为 str 实例。我们将此类代码标记为 Unicode-safe。Unicode-safe 库可以在全 unicode 世界中使用。
其次,我们需要能够编写代码,当仅提供 str 实例时,不会创建 unicode 结果。我们将此类代码标记为 str-stable。str-stable 的库可以被尚未 Unicode-safe 的库和应用程序使用。
有时编写既 str-stable 又 Unicode-safe 的代码很简单。例如,以下函数可以直接工作
def appendx(s):
return s + 'x'
这并不令人惊讶,因为 unicode 类型旨在简化任务。原则是当 str 和 unicode 实例相遇时,结果是一个 unicode 实例。一个显著的困难出现在代码需要对象的字符串表示时;这种操作传统上通过使用内置函数 str() 来完成。
使用当前的 str() 函数会使代码不 Unicode-safe。将 str() 调用替换为 unicode() 调用会使代码不 str-stable。更改 str() 使其能够返回 unicode 实例将解决此问题。作为额外的好处,一些当前不 Unicode-safe 的代码(因为它使用了 str())将变得 Unicode-safe。
规范
内置函数 str() 的 Python 实现如下
def str(s):
"""Return a nice string representation of the object. The
return value is a str or unicode instance.
"""
if type(s) is str or type(s) is unicode:
return s
r = s.__str__()
if not isinstance(r, (str, unicode)):
raise TypeError('__str__ returned non-string')
return r
以下函数将添加到 C API 中,并且将等同于内置函数 str()(理想情况下它应该被称为 PyObject_Str,但更改该函数可能会导致大量兼容性问题)
PyObject *PyString_New(PyObject *);
一个参考实现作为补丁在 Sourceforge [1] 上提供。
向后兼容性
某些代码可能要求 str() 返回 str 实例。在标准库中,迄今为止只发现了一个这样的情况。函数 email.header_decode() 需要一个 str 实例,而 email.Header.decode_header() 函数通过对其参数调用 str() 来尝试确保这一点。该代码通过将“header = str(header)”行更改为以下内容来修复
if isinstance(header, unicode):
header = header.encode('ascii')
这是否真的是一个 bug 值得商榷,因为 decode_header() 实际上操作的是字节字符串,而不是字符字符串。传递 unicode 实例的代码本身可能被认为是错误的。
替代解决方案
可以添加一个新的内置函数来代替更改 str()。这样做几乎不会引入向后兼容性问题。然而,由于兼容性问题预计会很少,更改 str() 似乎比添加新内置函数更可取。
basestring 类型可以更改为具有建议的行为,而不是更改 str()。然而,对于抽象基类型来说,这将是令人困惑的行为。
参考资料
版权
本文档已置于公共领域。
来源:https://github.com/python/peps/blob/main/peps/pep-0349.rst