【问题标题】:How do I get compatible type() behaviour in python 2 & 3 with unicode_literals?如何使用 unicode_literals 在 python 2 和 3 中获得兼容的 type() 行为?
【发布时间】:2017-08-13 22:29:00
【问题描述】:

这个问题看起来与this one 惊人地相似,但是那里的 cmets 中的建议不起作用(不再起作用?),如下所示。

我正在尝试编写一个兼容 python2-3 的包,我的一个方法中有一个类生成器,type() 在 python-2.7 测试中给我带来了问题:

Python 2.7.13 (default, Mar 18 2017, 17:03:32) 
[GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from __future__ import unicode_literals
>>> from builtins import str
>>> type('MyClass', (object,), {})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: type() argument 1 must be string, not unicode
>>> type(str('MyClass'), (object,), {})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: type() argument 1 must be string, not newstr

Python-Future overview 页面显示:

# Compatible output from isinstance() across Py2/3:
assert isinstance(2**64, int)        # long integers
assert isinstance(u'blah', str)
assert isinstance('blah', str)       # only if unicode_literals is in effect

我希望这会给我在任何需要字符串的地方提供一致的行为,但显然不是。

什么是正确的、独立于版本的方法?我链接到的另一个问题是在 python-2.6 时代提出的,从那时起行为似乎发生了变化。我认为我不能只转储 unicode_literals,因为如果我没有它,我会在调用 hashlib 时遇到可移植性问题(在其他地方)。

【问题讨论】:

  • 为什么要导入 unicode_literals?它似乎比解决方案更多的问题,对于这个特定的例子,你不需要它来让它在 py2 和 py3 中工作
  • 除非您正在执行一些需要区分字节字符串和 unicode 字符串的字符串操作,和/或您正在执行解码和编码等,那么您很可能不需要 unicode_literal,将其保留为是的,它可以在 py2 和 py3 中正常工作
  • 我不能保证传递给这个库的字符串永远不会是 Unicode。还有一些方法明确需要 Unicode 字符串。似乎在 2-3 代码中处理该问题的推荐方法是使用 unicode_literals。

标签: python python-2.7 python-unicode python-3.6


【解决方案1】:

不要使用builtins.str(),使用 Python 版本附带的普通 str

>>> from __future__ import unicode_literals
>>> type(str('MyClass'), (object,), {})
<class '__main__.MyClass'>

这适用于 Python 2 和 3。如果 future.builtins 模块默认替换 str 内置类型,请使用 __builtin__ 模块:

try:
    # Python 2
    from __builtin__ import str as builtin_str
except ImportError:
    # Python 3
    from builtins import str as builtin_str

MyClass = type(builtin_str('MyClass'), (object,), {})

【讨论】:

  • 看起来我实际上需要混合使用 this 和 builtins.str() ...在我的代码中的大多数地方我需要 Python3 兼容的 builtins.str() 行为(例如期望 issubclass(x, str) 为 unicode 文字返回 True),然后对于一些极少数特定情况(如 type()),我需要 __builtin__.str()。看起来对吗?
  • @mpounsett:当然,您需要做的就是通过将它们分配给不同的名称来确保将它们分开。因为future.builtins 模块是Python 3 builtins 模块的一个插入垫片,所以继续使用from builtins import str,但是使用try..except ImportErrorimport .. as ... 技巧来保持对Python 2 @ 的访问987654333@ 使用不同名称的对象。
猜你喜欢
  • 2013-06-02
  • 2013-11-06
  • 1970-01-01
  • 1970-01-01
  • 2014-03-13
  • 1970-01-01
  • 1970-01-01
  • 2013-05-13
  • 2016-11-30
相关资源
最近更新 更多