如何解决来自 pyright 的 "type is partially unknown" 警告?
How to solve "type is partially unknown" warning from pyright?
我正在通过 pyright 使用严格的类型检查。
当我有一个 return 是 pytorch DataLoader
的方法时,pyright 会抱怨我的类型定义:
Declared return type, "DataLoader[Unknown]", is partially unknown
Pyright (reportUnknownVariableType)
查看 pytorch 的类型存根 DataLoader
(减少到重要部分):
class DataLoader(Generic[T_co]):
dataset: Dataset[T_co]
@overload
def __init__(self, dataset: Dataset[T_co], ...
据我所知,DataLoader
的通用类型 T_co
应该由 __init__
数据集参数定义。
Pyright 还抱怨我的 Dataset
类型定义:
Type of parameter "dataset" is partially unknown
Parameter type is "Dataset[Unknown]"
Pyright (reportUnknownParameterType)
查看 Dataset
类型存根:
class Dataset(Generic[T_co]):
def __getitem__(self, index: int) -> T_co: ...
向我表明类型应该由 __getitem__
的 return 类型推断。
我的数据集 __getitem__
的类型签名如下所示:
def __getitem__(self, index: int) -> Tuple[Tensor, Tensor]:
基于此,我希望 Dataset
和 DataLoader
可以推断为 Dataset[Tuple[Tensor, Tensor]]
和 DataLoader[Tuple[Tensor, Tensor]]
,但事实并非如此。
我的猜测是 pyright 无法在此处静态推断类型。
我想我可以这样定义我自己的类型签名:
Dataset[Tuple[Tensor, Tensor]]
但这实际上导致我的 python 脚本崩溃:
TypeError: 'type' object is not subscriptable
如何正确定义 Dataset
和 DataLoader
的类型?
由于没有人回答这个问题,我不确定它是否真的是 pyright 中的一个错误。因此,我在 github 存储库上打开了这个问题:https://github.com/microsoft/pyright/issues/698
Eric Traut 详细解释了问题所在以及 pyright 正在按设计运行。
我试着在这里给出要点的要点。
问题解释
如果未提供 return 类型,Pyright 会尝试推断它们,但如果像本例那样提供,则需要完全键入。 Pyright 不会填写给定类型注释的缺失部分。
例如,pyright 将尝试为以下函数定义推断 return 类型:
def get_dataset():
但是如果 return 类型被指定为 Dataset
那么这就是 pyright 期望的 return 类型。
def get_dataset() -> Dataset:
在这种情况下,Dataset
是一个通用的 class,它不像 Dataset[int]
那样处理下标。
在 Python 3.7(我们正在使用的)中,Python 解释器将评估这些类型注释是什么导致了上述异常。
解决方案
从 Python 3.10 开始,Python 解释器将不再评估类型注释,以下类型注释将正常工作:
def get_dataset() -> Dataset[int]:
从 Python 3.7 开始,可以通过以下导入启用此行为:
from __future__ import annotations
PEP 563 中对此进行了记录。
您还需要禁用规则 E1136 以使 pylint 不警告 "unsubscriptable-object".
另一种解决方法是像这样引用类型定义:
def get_dataset() -> "Dataset[int]":
我正在通过 pyright 使用严格的类型检查。
当我有一个 return 是 pytorch DataLoader
的方法时,pyright 会抱怨我的类型定义:
Declared return type, "DataLoader[Unknown]", is partially unknown Pyright (reportUnknownVariableType)
查看 pytorch 的类型存根 DataLoader
(减少到重要部分):
class DataLoader(Generic[T_co]):
dataset: Dataset[T_co]
@overload
def __init__(self, dataset: Dataset[T_co], ...
据我所知,DataLoader
的通用类型 T_co
应该由 __init__
数据集参数定义。
Pyright 还抱怨我的 Dataset
类型定义:
Type of parameter "dataset" is partially unknown Parameter type is "Dataset[Unknown]" Pyright (reportUnknownParameterType)
查看 Dataset
类型存根:
class Dataset(Generic[T_co]):
def __getitem__(self, index: int) -> T_co: ...
向我表明类型应该由 __getitem__
的 return 类型推断。
我的数据集 __getitem__
的类型签名如下所示:
def __getitem__(self, index: int) -> Tuple[Tensor, Tensor]:
基于此,我希望 Dataset
和 DataLoader
可以推断为 Dataset[Tuple[Tensor, Tensor]]
和 DataLoader[Tuple[Tensor, Tensor]]
,但事实并非如此。
我的猜测是 pyright 无法在此处静态推断类型。
我想我可以这样定义我自己的类型签名:
Dataset[Tuple[Tensor, Tensor]]
但这实际上导致我的 python 脚本崩溃:
TypeError: 'type' object is not subscriptable
如何正确定义 Dataset
和 DataLoader
的类型?
由于没有人回答这个问题,我不确定它是否真的是 pyright 中的一个错误。因此,我在 github 存储库上打开了这个问题:https://github.com/microsoft/pyright/issues/698
Eric Traut 详细解释了问题所在以及 pyright 正在按设计运行。 我试着在这里给出要点的要点。
问题解释
如果未提供 return 类型,Pyright 会尝试推断它们,但如果像本例那样提供,则需要完全键入。 Pyright 不会填写给定类型注释的缺失部分。
例如,pyright 将尝试为以下函数定义推断 return 类型:
def get_dataset():
但是如果 return 类型被指定为 Dataset
那么这就是 pyright 期望的 return 类型。
def get_dataset() -> Dataset:
在这种情况下,Dataset
是一个通用的 class,它不像 Dataset[int]
那样处理下标。
在 Python 3.7(我们正在使用的)中,Python 解释器将评估这些类型注释是什么导致了上述异常。
解决方案
从 Python 3.10 开始,Python 解释器将不再评估类型注释,以下类型注释将正常工作:
def get_dataset() -> Dataset[int]:
从 Python 3.7 开始,可以通过以下导入启用此行为:
from __future__ import annotations
PEP 563 中对此进行了记录。 您还需要禁用规则 E1136 以使 pylint 不警告 "unsubscriptable-object".
另一种解决方法是像这样引用类型定义:
def get_dataset() -> "Dataset[int]":