'pytype' 使用 TypeVar 引发函数失败

'pytype' raises FAILED for function using TypeVar

我正在使用pytype(2019.10.17,目前最新版本)作为我的代码类型检查器开发了一个工具,可以通过索引文件随机读取msgpack文件,这记录每条消息的位置(msgpack文件中的偏移量)(msgpack中存储的值)。

在消息类型的多样性方面,我使用typing.TypeVar实现了泛型。 pytype 使用 TypeVar 时遇到问题。

Name: pytype
Version: 2019.10.17
Summary: Python type inferencer
Home-page: https://google.github.io/pytype
Author: None
Author-email: None
License: UNKNOWN
Location: /home/gaoyunpeng/miniconda3/envs/restore/lib/python3.6/site-packages
Requires: ninja, typed-ast, six, importlab, pyyaml, attrs
Required-by:
Python 3.6.4 :: Anaconda, Inc.
from typing import TypeVar
T = TypeVar('T')

def f(x: T):
  print(x)

运行 上面的代码加上命令:pytype main2.py:

Computing dependencies
Analyzing 1 sources with 0 local dependencies
ninja: Entering directory `/home/gaoyunpeng/workspace/.pytype'
[1/1] check main2
FAILED: /home/gaoyunpeng/workspace/.pytype/pyi/main2.pyi
pytype-single --imports_info /home/gaoyunpeng/workspace/.pytype/imports/main2.imports --module-name main2 -V 3.6 -o /home/gaoyunpeng/workspace/.pytype/pyi/main2.pyi --analyze-annotated --nofail --quick /home/gaoyunp
eng/workspace/main2.py
File "/home/gaoyunpeng/workspace/main2.py", line 4, in <module>: Invalid type annotation 'T'  [invalid-annotation]
  Appears only once in the signature

For more details, see https://google.github.io/pytype/errors.html#invalid-annotation.
ninja: build stopped: subcommand failed.

https://google.github.io/pytype/errors.html#invalid-annotation所述,这种情况是无效注释。

为什么代码无法通过pytype检查?

打印出来的错误信息解释了为什么这是一个类型错误。正如节目所说。引用错误信息的相关部分:

File "/home/gaoyunpeng/workspace/main2.py", line 4, in <module>: Invalid type annotation 'T'  [invalid-annotation]
  Appears only once in the signature

在给定的签​​名中只使用一次 TypeVar 是错误的,因为这样做毫无意义。在您的情况下,您也可以只使用类型签名 def f(x: object) -> None 。你想说 f 可以接受任何东西, Python 中的所有东西都是 object.

的子类型

仅当您想要坚持两种或多种类型完全相同时,才应使用泛型类型。例如,如果您想定义一个“身份”函数,使用泛型类型是正确的:

def identity(x: T) -> T:
    return x

这将允许类型检查器推断 identity("foo")identity(4) 分别是 str 和 int 类型——return 类型总是与参数类型相同.

请注意,“您应该始终在每个签名中使用 TypeVar 两次或多次”这一规则对于泛型 类 中的方法也适用。当你这样做时:

class Foo(Generic[T]):
    def test(self, x: T) -> None: pass

...test的签名其实是def test(self: Foo[T], x: T) -> None。所以我们也隐含地总是在那里使用两次 TypeVar。