Странное поведение при указании типа dict.items() в PyCharm

Скажем, у меня есть функция do_something:

from typing import *

def do_something(argument: Sequence[Tuple[int, str]]):
    pass

Скажем, у меня также есть словарь D, ключи которого — исключительно целые числа, а значения — исключительно строки:

D: Dict[int, str] = {1: 'a', 2: 'b', 3: 'c'}

В PyCharm это с честью пройдет проверку типов:

do_something(
    ((1, 'a'), (2, 'b'), (3, 'c'))
)

Но это, согласно PyCharm, не работает с проверкой типов, несмотря на то, что то, что она производит, идентично:

do_something(tuple(D.items()))

Это ожидаемое поведение - я что-то здесь упустил? -- или это ошибка с проверкой типов PyCharm?


person Alex Waygood    schedule 15.03.2021    source источник


Ответы (2)


Это ошибка в PyCharm. Есть много подобных ошибок, например. это, это, это.

В общем, PyCharm довольно умно подходит к этому. Он правильно определяет тип D в вашем случае. Он также правильно выводит D.items(), а затем в таком коде, как for k, v in D.items(), k и v, будут правильно выведены. Но по какой-то странной причине tuple/list/sorted или что-то около D.items() глючит.

Я всегда сообщал о проблеме на Youtrack, когда вы ожидали, что это должно работать.

person Albert    schedule 15.03.2021
comment
Мне все еще было бы любопытно узнать, подходит ли Mypy к этому. - person AKX; 16.03.2021

PyCharm не может гарантировать, что тип D действительно будет Dict[str, int]; вероятно, он не выполняет анализ потока кода, чтобы убедиться, что ничто не может добавить в dict пару, отличную от (str, int). (Кроме того, вы должны посмотреть, может ли Mypy, каноническая проверка типов для Python.)

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

D: Dict[str, int] = {1: 'a', 2: 'b', 3: 'c'}
person AKX    schedule 15.03.2021
comment
Это имеет смысл, спасибо. Да, я попытался явно указать, что ключи и значения словаря всегда должны иметь согласованные типы. К сожалению, ничего не происходит (хотя, очевидно, это не серьезная проблема). - person Alex Waygood; 16.03.2021
comment
Если добавление явного типа не помогает, возможно, нет явного или неявного ввода, говорящего, что tuple(x.items()) для x, то есть Dict[K, V], является Sequence[Tuple[K, V]]... - person AKX; 16.03.2021
comment
Да, я думаю, что это более глубокая проблема. Я попытался настроить подсказки типов в самой функции на: def DoSomething(argument: Sequence[Tuple[Any, Any]]): pass, и проблема все еще существует. Независимо от того, какие типы ключей и значений любого данного словаря, мне кажется, что tuple(Dict.items()) всегда будет иметь тип Sequence[Tuple[Any, Any]]. Так что это просто не имеет логического смысла для меня. - person Alex Waygood; 16.03.2021
comment
Хммм... Попробуйте Iterable[Tuple[K, V]] - я думаю, что Sequence должны индексироваться, но .items() точно нет. - person AKX; 16.03.2021
comment
Все равно нет! Судя по примерам, на которые я указал в другом ответе, похоже, что это, вероятно, просто ошибка PyCharm. - person Alex Waygood; 16.03.2021