最近我在 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 推断的类型。
感谢@STerliakov!我已在官方 pylance GitHub 存储库中针对此错误提交了“问题”。 回复是这种行为是有意为之,而不是错误:
此行为是有意为之,所以我不认为这是一个错误。我可以理解为什么这看起来不一致,但这是有充分理由的。implicitPyright(构建 pylance 的类型检查器)区分显式
Any
和隐式
。当启用类型检查时,将后者称为Any
。有关更多详细信息,请参阅Unknown
此文档。在大多数情况下,pyright 将Any
和视为相同,但在严格类型检查模式下,它允许您在尝试使用Unknown
类型时收到具体通知。假设是,如果您明确指定了Unknown
,则您已经承认您放弃了类型安全,但如果您有Any
,您将希望被告知这一点。因此,当缩小分配类型时,pyright 会保留Unknown
。在第一个示例中,参数Unknown
的类型是array
,因为您尚未为其提供任何类型注释。这意味着表达式Unknown
的类型也是array.tolist()
。当将其分配给变量Unknown
时,其类型从result
缩小到list
。这会保留list | Unknown
,因此如果您随后使用此值并且启用了严格类型检查模式,您将收到有关其使用的通知。当您禁用类型检查(即将 typeCheckingMode 设置为“off”)时,pylance 将Unknown
Unknown
显示为
,即使在内部 pright 跟踪的类型是Any
。 Pyright 是 Pylance 中使用的类型检查器,Pyright 将Unknown
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
)。