Strange behaviour when type-hinting dict.items() in PyCharm

Viewed 331

Say I have a function, do_something:

from typing import Sequence, Tuple, Dict

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

Say I also have a dictionary, D, the keys of which are solely ints, and the values of which are solely strs:

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

In PyCharm, this will pass the type-checker with flying colours:

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

But this, according to PyCharm, fails the type-checker, despite being identical in what it produces:

do_something(tuple(D.items()))

Is this expected behaviour -- am I missing something here? -- or is this a bug with PyCharm's type-checker?

2 Answers

This is a bug in PyCharm. There are many similar bugs, e.g. this, this, this.

In general, PyCharm is pretty clever about this. It correctly infers the type of D in your case. It also correctly infers D.items(), and then in code like for k, v in D.items(), k and v will be correctly inferred. But for some strange reason, tuple/list/sorted or sth around D.items() is buggy.

I would always report an issue on Youtrack when you would expect that it should work.

PyCharm can't guarantee the type of D to really be Dict[str, int]; it probably doesn't do code flow analysis to make sure nothing can't have added a non-(str, int) pair into the dict. (As an aside, you should see if Mypy, the "canonical" type checker for Python, can.)

You might be able to add the explicit type annotation to see if that helps.

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