unicode_literals和type()

jpi*_*pic 12 python python-2.x python-3.x six-python

我在type()调用时支持python2和python3时遇到问题.这证明了这个问题:

from __future__ import unicode_literals

name='FooClass'
type(name, (dict,), {})
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

这与在Python 2.6中使用unicode_literals的Any gotchas有关吗?.在那个问题中,有人建议对一个字节串进行类型转换,所以天真地考虑使用six.b():

一个"假的"字节文字.数据应始终是正常的字符串文字.在Python 2中,b()返回一个8位字符串.在Python 3中,数据使用latin-1编码编码为字节.

所以它看起来像这样:

from __future__ import unicode_literals
import six

name='FooClass'
type(six.b(name), (dict,), {})
Run Code Online (Sandbox Code Playgroud)

但它在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
Run Code Online (Sandbox Code Playgroud)

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

你怎么看 ?

有什么我不明白的吗?

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

没有办法同时type()支持2和3?

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

小智 14

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

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