PyCharm does not recognize dictionary value type

2019-05-11 04:54发布

I have a simple code snippet where I set dictionary values as empty lists:

new_dict = {}
for i in range(1, 13):
    new_dict[i] = []

Now, if inside the loop on the next line I would type new_dict[i] and add a dot, I expect PyCharm to show me a list of methods available for a list, but PyCharm fails to recognize the dictionary value type in this simple case:

enter image description here

Why is it happening and what can I do? Using PyCharm 2016.1.2, Python 2.7.10.


As a workaround, I can explicitly add a type hint, letting PyCharm know that new_dict is a dictionary where keys are integers and values are lists by adding a # type: dict[int, list] inline comment:

enter image description here

2条回答
你好瞎i
2楼-- · 2019-05-11 05:22

Lets consider a slightly more complex scenario with a variable:

for i in range(10):
    if i%2:
        x = 3
    else:
        x = "hello"
    x. #type hint for both int and str

In this case the last line will give us all the methods of ints and strs because PyCharm is able to detect that x will either be an int or a str

Now replace all the occurences of x with my_dict[i]:

my_dict = {}
for i in range(10):
    if i%2:
        my_dict[i] = 3
    else:
        my_dict[i] = "hello"
    my_dict[i]. #no type hint :(

All of the same rules apply as above, we know (and PyCharm would be able to figure out) that my_dict[i] is either going to be an int or a str.

However what would you expect to happen if you were not initializing the dict?

def f(my_dict): #or even (my_dict:dict)
    my_dict[1]. #cannot possibly expect a type hint

In this case there is no way to know what the values of the dict are other then adding an explicit annotation just like you would in your example case:

def f(my_dict:"dict[int,list]"):
    my_dict[1]. #get all the list methods

This really reinforces some lines from The Zen of Python:

Explicit is better than implicit.
Readability counts.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.

(I include readability because the explicit type hint is a lot easier to read then a potentially buried assignment)

查看更多
beautiful°
3楼-- · 2019-05-11 05:36

I think you are expecting PyCharm to be able to infer too much from the code.

Providing the type hint annotation gives PyCharm the information it needs to show the code completion options. In this case you are explicitly telling PyCharm what type the value of each dictionary element is going to be.

Without the type hint annotation you are expecting PyCharm to be able to know what the dictionary's element value is going to be when you are assigning it inside of a loop. That is way too much assumption for PyCharm to make. As Tadhg McDonald-Jensen mentioned in the comments, this is just too dynamic of a situation for PyCharm to figure it out reliably. The code completion would be wrong too often.

查看更多
登录 后发表回答