微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

VSCode:使用非本地导致变量类型“从不”

如何解决VSCode:使用非本地导致变量类型“从不”

我发现 VSCode/Pylance 有一些 Python 代码的奇怪行为。考虑以下最小示例:

#!/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__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

上发布了问题

解决方法

根据关于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 问题中的解释:行 x: Optional[list] = None 使 x 的类型为 None,因为它实际上是这样的,无论类型如何宣布。现在,缺少对函数x 内部f 突变的分析,当到达x 行时None 的类型仍然是assert isinstance(x,list)。由于类型 None 不是 list 的实例,对于类型检查器,这一行永远不会通过。为了表明这一点,x 的类型因此设置为 Never

,

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

enter image description here

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

enter image description here

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。