13

我在type()通话中支持 python2 和 python3 时遇到问题。这说明了问题:

from __future__ import unicode_literals

name='FooClass'
type(name, (dict,), {})

在 python3 上没问题,但在 python2 上:

Traceback (most recent call last):
  File "test.py", line 6, in <module>
    type(name, (dict,), {})
TypeError: type() argument 1 must be string, not unicode

这与Python 2.6 中使用 unicode_literals 的任何陷阱有关吗?. 在那个问题中,有人建议将类型转换为字节字符串,所以我天真地考虑使用six.b()

“假”字节文字。data 应该始终是一个普通的字符串文字。在 Python 2 中,b() 返回一个 8 位字符串。在 Python 3 中,数据使用 latin-1 编码为字节。

所以它看起来像这样:

from __future__ import unicode_literals
import six

name='FooClass'
type(six.b(name), (dict,), {})

但它在 python2 和 python3 上都失败了:

$ python2 test.py 
Traceback (most recent call last):
  File "test.py", line 6, in <module>
    type(six.b(name), (dict,), {})
TypeError: type() argument 1 must be string, not unicode

$ python3 test.py 
Traceback (most recent call last):
  File "test.py", line 6, in <module>
    type(six.b(name), (dict,), {})
TypeError: type() argument 1 must be str, not bytes

所以看起来真的type()想要一个python2 str,它是python2上的python3字节字符串,但它想要一个python3 str,它是python3上的python2 unicode字符串。

你怎么看 ?

有什么我不明白的吗?

type()或者在 python 2 和 3 上是否存在真正的不兼容?

没有办法让相同的type()呼叫同时支持 2 和 3 ?

在这种情况下,不应该像six提供包装器这样的工具type()吗?

4

1 回答 1

16

six.b是在您不会使用的假设下编写的unicode_literals(并且您将向它传递一个字符串文字,如文档所述),因此 Python 2 实现就像def b(s): return sPython 2 字符串文字已经是一个字节字符串一样。

要么不要unicode_literals在这个模块中使用,要么使用(正如评论所建议的那样)str(name)。在 Python 3 中,这是一个空操作。在 Python 2 中,它默默地将 unicode 字符串转换为字节字符串(假设一些我懒得记住的编码,但它是 ASCII 的超集,所以你应该没问题)。

于 2013-10-27T12:40:03.990 回答