Как решить предупреждение "тип частично неизвестен" от pyright?

Я использую строгую проверку типов через pyright.

Когда у меня есть метод, возвращающий pytorch DataLoader, то Пайрайт жалуется на определение моего типа:

Объявленный возвращаемый тип "DataLoader[Unknown]" частично неизвестен Pyright (reportUnknownVariableType)

Взглянув на заглушку типа от pytorch's DataLoader (сведено к важным частям):

class DataLoader(Generic[T_co]):
    dataset: Dataset[T_co]

    @overload
    def __init__(self, dataset: Dataset[T_co], ...

Насколько я понимаю, общий тип T_co из DataLoader должен быть определен __init__ параметр набора данных.

Пайрайт также жалуется на мои Dataset определение типа:

Тип параметра "набор данных" частично неизвестен. Тип параметра - "Набор данных [Неизвестно]" 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: объект типа не может быть подписан

Как правильно определить тип для Dataset а также DataLoader?

2 ответа

Решение

Поскольку на этот вопрос не было ответа, я не был уверен, действительно ли это ошибка в pyright. Поэтому я открыл эту проблему в репозитории github: https://github.com/microsoft/pyright/issues/698

Эрик Траут подробно объяснил, в чем проблема, и что pyright работает так, как задумано. Здесь я постараюсь изложить суть основных моментов.

Объяснение проблемы

Pyright пытается определить возвращаемые типы, если они не предоставлены, но если они предоставлены, как в этом случае, они должны быть полностью типизированы.Pyright не заполняет недостающие части аннотации данного типа.

Например, pyright попытается вывести тип возвращаемого значения для следующего определения функции:

def get_dataset():

Но если тип возврата задан как Dataset тогда это тип возвращаемого значения, которого ожидает pyright.

def get_dataset() -> Dataset:

В этом случае Dataset - это общий класс, который не обрабатывает индексы вроде 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 не предупреждал о "неподписываемом-объекте".

Другой обходной путь - процитировать определение типа следующим образом:

def get_dataset() -> "Dataset[int]":
      "python.analysis.diagnosticSeverityOverrides": {
    "reportUnknownVariableType": "none",
    "reportUnknownArgumentType": "none",
    "reportUnknownLambdaType": "none",
    "reportUnknownMemberType": "none",
    "reportUnknownParameterType": "none",
    "reportMissingParameterType": "none"
  }
Другие вопросы по тегам