mypy“无效类型”错误

Jam*_*ell 4 python mypy

我正在尝试在当前项目中实现类型注释,并且从mypy接收到了我不理解的错误。

我正在使用Python 2.7.11,并将新安装的mypy安装在基本virtualenv中。以下程序运行正常:

from __future__ import print_function
from types import StringTypes
from typing import List, Union, Callable

def f(value):     # type: (StringTypes) -> StringTypes
    return value

if __name__ == '__main__':
    print("{}".format(f('some text')))
    print("{}".format(f(u'some unicode text')))
Run Code Online (Sandbox Code Playgroud)

但是运行会mypy --py2 -s mypy_issue.py返回以下内容:

mypy_issue.py: note: In function "f":
mypy_issue.py:8: error: Invalid type "types.StringTypes"
Run Code Online (Sandbox Code Playgroud)

上面的类型似乎在Typeshed中 ... mypy 文档说:“ Mypy包含了typeshed项目,该项目包含Python内置文件和标准库的库存根。” ...不确定“ incorporates”是什么意思-我需要吗做一些事情来“激活”或提供Typeshed的路径?我是否需要在本地下载并安装(?)Typeshed?

Mic*_*x2a 6

问题是types.StringTypes定义为类型序列-Typeshed上的正式类型签名为:

StringTypes = (StringType, UnicodeType)
Run Code Online (Sandbox Code Playgroud)

这对应于官方文档,该文档指出该StringTypes常量是“包含StringTypeUnicodeType... 的序列”。

因此,这就说明了您遇到的错误- StringTypes不是实际的类(可能是一个元组),因此mypy无法将其识别为有效类型。

有几个可能的修复程序。

第一种方法可能是使用typing.AnyStr定义为AnyStr = TypeVar('AnyStr', bytes, unicode)。尽管模块中AnyStr包含该typing模块,但遗憾的是,到目前为止,该文档的记录还很差-您可以在mypy docs中找到有关其功能的更多详细信息。

稍微干净一点的表达方式是:

from types import StringType, UnicodeType
from typing import Union

MyStringTypes = Union[StringType, UnicodeType]

def f(value):     
    # type: (MyStringTypes) -> MyStringTypes
    return value
Run Code Online (Sandbox Code Playgroud)

这也有效,但是由于返回类型不再与输入类型相同,而在使用不同类型的字符串时通常不是您想要的类型,因此返回类型不再是必需的。

至于排版-默认情况下,在安装mypy时将其捆绑在一起。在理想的世界中,您根本不必担心输入错误,但是由于mypy在beta中,因此频繁更新输入错误以解决缺少的模块或错误的类型注释,可能值得直接从Github安装mypy 如果您发现自己经常遇到Typeshed的错误,请在本地进行repo和安装typeshed。

  • @SolomonUcko -- 不。问题在于`types` 标准库模块早于类型提示,实际上更多用于运行时使用,而不是类型提示使用。尽管名称如此,mypy(以及任何其他符合 PEP 484 的类型检查器)不会将 `StringTypes` 识别为有效类型:它最终被视为只是一个恰好包含两种类型的元组。我的建议是避免在类型提示的上下文中使用 `types` 模块中的任何内容。相反,尽可能使用 `typing` 模块中的内容——因此在这种情况下,使用 `typing.AnyStr` 或 `Union[str, typing.Text]`。 (2认同)