如何使用类型注释覆盖 Pylance 推断的类型?

问题描述 投票:0回答:1

最近我在 VS Code 中尝试对函数中的变量进行类型注释时遇到了一个问题:

def f(array):
    # Pylance shows the type of b being `Any | list`,
    # which I think should be `list`.
    b: list = array.tolist()
    return b

在 VS Code 中,参数

array
被推断为
Any
:当我们将鼠标悬停在该变量上时,VS Code 会弹出一个提示,显示

(paramter) array: Any

这对我来说是合理的,因为我认为 Pylance 隐含地将

array
假定为
Any
类型。

但是当我尝试将变量

b
注释为类型
list
时,事情开始变得奇怪。 VS Code 推断
b
的类型是
Any | list
,我不明白。我希望 Pylance 尊重我的注释,而不是推断的
Any
。为什么结果是Union类型?

另外,我应该怎么做才能让我的注释覆盖推断的类型?

我尝试过使用

typing.cast
,它解决了这个问题,但我认为这有点尴尬。我想要的是我的注释可以覆盖 Pylance 推断的类型。

python visual-studio-code type-hinting python-typing pylance
1个回答
0
投票

感谢@STerliakov!我已在官方 pylance GitHub 存储库中针对此错误提交了“问题”。 回复是这种行为是有意为之,而不是错误:

此行为是有意为之,所以我不认为这是一个错误。我可以理解为什么这看起来不一致,但这是有充分理由的。

Pyright(构建 pylance 的类型检查器)区分显式

Any

和隐式

Any
。当启用类型检查时,将后者称为
Unknown
。有关更多详细信息,请参阅
此文档
。在大多数情况下,pyright 将 Any
Unknown
视为相同,但在严格类型检查模式下,它允许您在尝试使用
Unknown
类型时收到具体通知。假设是,如果您明确指定了
Any
,则您已经承认您放弃了类型安全,但如果您有
Unknown
,您将希望被告知这一点。因此,当缩小分配类型时,pyright 会保留
Unknown
。在第一个示例中,参数
array
的类型是
Unknown
,因为您尚未为其提供任何类型注释。这意味着表达式
array.tolist()
的类型也是
Unknown
。当将其分配给变量
result
时,其类型从
list
缩小到
list | Unknown
。这会保留
Unknown
,因此如果您随后使用此值并且启用了严格类型检查模式,您将收到有关其使用的通知。
当您禁用类型检查(即将 typeCheckingMode 设置为“off”)时,pylance 将 

Unknown

显示为

Any
,即使在内部 pright 跟踪的类型是
Unknown

Pyright 是 Pylance 中使用的类型检查器,Pyright 将
implicit

Any 视为

Unknown
。 对于
Unknown
的变量,会保留
Unknown
类型进行操作,这样我们就可以得知“存在一个部分未知类型的变量”。 此外,在 VS Code 中,当
python.analysis.typeCheckingMode
设置为
off
(默认)而不是
basic
strict
时,
Unknown
将显示为
Any
所以现在我认为

使用Pyright

,要将变量b的推断类型覆盖为

list
,我们需要使用
typing.cast
:
b = typing.cast(list, array.tolist())

或者我们修复 
Unknown

类型的起源(在我的示例中,通过将

array
注释为
Any
np.ndarray
)。
    

© www.soinside.com 2019 - 2024. All rights reserved.