Исправить ошибку mypy

Проверяю свой код анализатором mypy. Возникли следующие ошибки:

  1. Имеется объект names: List[str], на выражение len(names) выдается ошибка

    Argument 1 to "len" has incompatible type "Optional[List[str]]"; expected "Sized"

    При индексации names[i] выдается следующая ошибка:

    Value of type "Optional[List[str]]" is not indexable

  2. Имеется объект matrix: List[List[int]], аналогично при индексации matrix[i][j]

    Value of type "Optional[List[List[int]]]" is not indexable

  3. Имеется объект

     def func() -> Dict[str, List[str]]
         g = {"1": ["2"],
             "2": ["3"]}
         return g
    

    описанный как Dict[str, List[str]], вылетает ошибка:

    Incompatible return value type (got "Dict[str, object]", expected "Dict[str, List[str]]") Неясно, почему получился такой тип. Если изменить его на Dict[str, object], дальше по коду появляются ошибки.

  4. При обращении к объекту из п. 3:

     d: DefaultDict[str, List[str]] = defaultdict(list)
     for obj in g:
         d[obj].extend(g.get(obj))
    

    Вылетает следующая ошибка:

    Argument 1 to "extend" of "list" has incompatible type "Optional[List[str]]"; expected "Iterable[str]"

Я новичок в python и не очень понимаю принципы корректной работы с mypy - как мне грамотно писать аннотации к типам, чтобы не получать таких ошибок?


Ответы (1 шт):

Автор решения: insolor

1 и 2:

Optional говорит о том, что у вас значение может быть не только заданного через аннотацию типа, но и None - например, если None задано в значении параметра по-умолчанию для функции. Дальше вы не проверяя значение на None пытаетесь с этими значениями работать как со списками. Нужно добавить проверку на None, тогда ошибок не будет.

Пример:

# Неправильно:
def test(names: List[str]=None, matrix: List[List[int]]=None):
    print(names[0])  # Ошибка: Value of type "Optional[List[str]]" is not indexable
    print(len(names))  # Ошибка: Argument 1 to "len" has incompatible type "Optional[List[str]]"; expected "Sized"
    print(matrix[0][0])  # Ошибка: Value of type "Optional[List[List[int]]]" is not indexable


# Правильно:
def test(names: List[str]=None, matrix: List[List[int]]=None):
    if names is not None:
        print(names[0])
        print(len(names))

    if matrix is not None:
        print(matrix[0][0])

3:

Вы забыли двоеточие в конце строки def, а так mypy ошибок не выдает:

def func() -> Dict[str, List[str]]:  # <-- добавил двоеточие
    g = {"1": ["2"],
        "2": ["3"]}
    return g

4:

Метод get словаря может возвращать None, если ключа в словаре нет (т.е. у него тип возвращаемого значения Optional[тип значения из словаря]). Т.к. ключи берутся из этого же словаря, то ситуация, когда вернется None, фактически невозможна, но mypy не настолько умный, чтобы это понимать. Нужно просто заменить получение значения через get на получение через квадратные скобки, тогда ошибка пропадет:

g = func()
d: DefaultDict[str, List[str]] = defaultdict(list)
for obj in g:
    d[obj].extend(g[obj])  # было g.get(obj), стало g[obj]
→ Ссылка