Mypy Python 2 坚持 unicode 值不是字符串值

Mypy Python 2 insist on unicode value not string value

Python 2 在某些情况下会隐式地将 str 转换为 unicode。此转换有时会抛出 UnicodeError,具体取决于您尝试对结果值执行的操作。我不知道确切的语义,但这是我想避免的事情。

是否可以使用unicode以外的其他类型或类似于--strict-optionalhttp://mypy-lang.blogspot.co.uk/2016/07/mypy-043-released.html)的命令行参数来导致使用此隐式转换的程序无法进行类型检查?

def returns_string_not_unicode():
    # type: () -> str
    return u"a"

def returns_unicode_not_string():
    # type: () -> unicode
    return "a"

在此示例中,只有函数 returns_string_not_unicode 无法进行类型检查。

$ mypy --py2 unicode.py
unicode.py: note: In function "returns_string_not_unicode":
unicode.py:3: error: Incompatible return value type (got "unicode", expected "str")

我希望他们都无法通过类型检查。

编辑:

type: () -> byte 似乎与 str

的处理方式相同
def returns_string_not_unicode():
    # type: () -> bytes
    return u"a"

不幸的是,这是一个持续存在且目前尚未解决的问题 -- 请参阅 https://github.com/python/mypy/issues/1141 and https://github.com/python/typing/issues/208

部分修复是使用 typing.Text,它(不幸的是)目前没有记录(不过我会努力修复它)。它在 Python 3 中别名为 str,在 Python 2 中别名为 unicode。它不会解决您的实际问题或导致第二个函数无法进行类型检查,但它 是否使编写与 Python 2 和 Python 3 兼容的类型变得更容易一些。

与此同时,您可以通过使用最近实现的 NewType feature 来拼凑部分解决方法——它允许您以最小的运行时间成本定义一个伪子类,您可以使用它来近似功能您正在寻找:

from typing import NewType, Text

# Tell mypy to treat 'Unicode' as a subtype of `Text`, which is
# aliased to 'unicode' in Python 2 and 'str' (aka unicode) in Python 3
Unicode = NewType('Unicode', Text)

def unicode_not_str(a: Unicode) -> Unicode:
    return a

# my_unicode is still the original string at runtime, but Mypy
# treats it as having a distinct type from `str` and `unicode`.
my_unicode = Unicode(u"some string")

unicode_not_str(my_unicode)      # typechecks
unicode_not_str("foo")           # fails
unicode_not_str(u"foo")          # fails, unfortunately
unicode_not_str(Unicode("bar"))  # works, unfortunately

它并不完美,但如果您有原则地确定何时将字符串提升为您的自定义 Unicode 类型,您可以获得接近您正在寻找的类型安全性的东西bytes/str/unicode 问题解决前的最低运行成本。

请注意,您需要从 Github 上的主分支安装 mypy 才能使用 NewType

请注意,从 mypy version 0.4.4 开始添加了 NewType。