1

我在一些 Python 代码中看到了 VSCode/Pylance 的奇怪行为。考虑以下最小示例:

#!/usr/bin/env python3

from typing import Optional

def main():
    x: Optional[list] = None
    def f():
        nonlocal x
        x = [10]
    f()
    assert isinstance(x, list)
    y: int = x[0] + 3
    assert isinstance(y, int)
    print(y)

main()

对 f() 的调用显然将外部设置x[10]. 将鼠标悬停x在第一条assert语句(在函数调用之后)显示(variable) x: None,没关系。但在assert声明之后,将鼠标悬停在 x 上显示(variable) x: Never。这会导致x以下所有行的语法突出显示和自动完成都失败,因为 VSCode/Pylance 显然看到了一个“无类型”的变量。打字x.甚至不显示对象的内置成员,如x.__class__or x.__doc__。分配x给另一个类型的变量没有帮助。第一个断言导致 mypy 接受代码,而 PyLint 说Value 'x' is unsubscriptable,因此其他工具之间似乎也存在一些分歧。这有点烦人,因为代码可以正常工作。

问题:这是 Pylance 中的错误吗?甚至是预期的行为?有什么方法可以强制 Pylance 看到正确的类型x

工具版本:

$ code --version
1.56.2
054a9295330880ed74ceaedda236253b4f39a335
x64
$ pylint --version
pylint 2.8.2
astroid 2.5.6
Python 3.8.5 (default, Jan 27 2021, 15:41:15) 
[GCC 9.3.0]
$ mypy --version
mypy 0.800

VSCode Python:v2021.5.842923320
VSCode Pylance:v2021.5.3

谢谢你和最好的问候,
菲利普

编辑:在GitHub 上发布问题

4

2 回答 2

2

根据GitHub 上的讨论,我会回答如下问题:

  • 这是 Pylance 中的错误吗?不是错误,但 Pyright(Pylance 的类型检查器)中实现的类型推断没有考虑由外部执行流(例如包含 的回调函数的运行)引起的局部突变nonlocal

  • 甚至是预期的行为?是的,至少部分考虑到上述观点。

  • 有什么方法可以强制 Pylance 看到正确的类型x是的,x = cast(list, x)在 之后使用assert isinstance(x, list)

使用cast,最小的示例如下所示:

#!/usr/bin/env python3

from typing import Optional, cast

def main():
    x: Optional[list] = None
    def f():
        nonlocal x
        x = [10]
    f()
    assert isinstance(x, list)
    x = cast(list, x)
    y: int = x[0] + 3  # Now x is reported as '(variable) x: list'
    assert isinstance(y, int)
    print(y)

main()

再多总结一下 GitHub 问题中的解释:该行由 type 组成x: Optional[list] = None,因为它实际上是这样的,无论类型是如何声明的。现在,缺少对内部函数突变的分析,到达该行时的类型仍然是。由于类型不是 的实例,因此对于类型检查器,此行将永远不会通过。为了表明这一点,因此将类型设置为。xNonexfxNoneassert isinstance(x, list)NonelistxNever

于 2021-05-28T05:43:52.863 回答
0

虽然将鼠标悬停在 show 上x,但在(variable) x: Never添加Settings.json然后Start Debugging时,您可以看到一个特殊的变量,它的属性确实是:"debug.inlineValues": truex__class__list

在此处输入图像描述

Jedi设置为语言服务器时,将鼠标悬停在 x 上为NoneTypelist

在此处输入图像描述

您可以在github/pylance-release中寻求更多帮助。

于 2021-05-27T03:15:57.937 回答