我正在通过pyright进行严格的类型检查。
当我有一个返回DataLoader的方法时,pyright会抱怨我的类型定义:
声明的返回类型"DataLoaderUnknown“是部分未知的Pyright (reportUnknownVariableType)
看一看pytorch的DataLoader的类型存根(简化为重要的部分):
class DataLoader(Generic[T_co]):
dataset: Dataset[T_co]
@overload
def __init__(self, dataset: Dataset[T_co], ...据我所见,T_co的泛型类型DataLoader应该由__init__ dataset参数定义。
Pyright还抱怨我的Dataset类型定义:
参数类型“数据集”是部分未知的参数类型是"DatasetUnknown“Pyright (reportUnknownParameterType)
查看一下Dataset类型存根:
class Dataset(Generic[T_co]):
def __getitem__(self, index: int) -> T_co: ...向我显示,该类型应该由__getitem__的返回类型推断。
我的数据集的__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”对象不可订阅
如何正确定义Dataset和DataLoader的类型
发布于 2020-05-30 16:52:53
由于这个问题没有得到回答,我不确定它是否真的是pyright中的一个bug。因此,我在github存储库上打开了这个问题:https://github.com/microsoft/pyright/issues/698
Eric详细解释了问题是什么,而pyright正在按设计工作。我在这里试图给出要点的要点。
问题解释
Pyright试图推断返回类型,如果没有提供它们,但是如果它们是像本例中那样提供的,则它们需要完全类型。Pyright不填充给定类型注释中缺少的部分。
例如,pyright将尝试为以下函数定义推断返回类型:
def get_dataset():但是,如果返回类型给定为Dataset,那么这就是pyright所期望的返回类型。
def get_dataset() -> Dataset:在本例中,Dataset是一个泛型类,它不像Dataset[int]那样处理订阅。在Python3.7(我们正在使用的)中,Python解释器将计算这些类型注释,从而导致上述异常。
解决方案
从Python3.10开始,Python解释器将不再计算类型注释,下面的类型注释将只起作用:
def get_dataset() -> Dataset[int]:从Python3.7开始,可以通过以下导入启用此行为:
from __future__ import annotations这在佩普563中有记录。您还需要禁用针对pylint的规则E1136,以避免对“不可订阅的对象”发出警告。
另一个解决办法是引用如下类型定义:
def get_dataset() -> "Dataset[int]":https://stackoverflow.com/questions/61997937
复制相似问题