5

I'm definitely not an expert of mypy, but there's an error that I'm really not understanding.

Let's say that I have this dictionary and I want to parse it and create another one through a dict comprehension.

my_dict = {
    'type1': {
        'category1': [
            'subcategory1',
            'subcategory2',
        ],
    },
    'type2': {
        'category2': [
            'subcategory3',
        ],
        'category3': [],
    },
}

The dict comprehension:

new_dict = {
    subcategory: {
        'category': category,
        'type': type,
    }
    for type, categories in my_dict.items()
    for category, subcategories in categories.items()
    for subcategory in subcategories
}

and the expected output:

{
    'subcategory1': {
        'category': 'category1',
        'type': 'type1'
    },
    'subcategory2': {
        'category': 'category1',
        'type': 'type1'
    },
    'subcategory3': {
        'category': 'category2',
        'type': 'type2'
    }
}

mypy in this situation complains because of the empty category3, but with an error message ('error:"object" has no attribute "items"') that refers to the previous line.

Any suggestion?

Thanks in advance

vhemt
  • 53
  • 2
  • 5
  • first off, `type` is a python keyword, do not use it as a variable ;) To me, running your code produces the expected output, or there's something I'm missing. – Marc Z Mar 28 '18 at 12:47
  • it's not actual code, I just didn't bother to find an alternative to `type` for the example :) The code works fine, it's `mypy` that raises an error. – vhemt Mar 28 '18 at 12:55

1 Answers1

5

The issue is mypy is unable to infer the type of my_dict -- it's too complicated for mypy to naturally infer the type.

You can confirm for yourself by adding the line reveal_type(my_dict) before running mypy. (Mypy special-cases that function name to help with debugging). The inferred type ended up being Dict[str, object], or something to that effect.

You can fix this by explicitly giving my_dict a type. If you're using Python 3.6+, you can use the new variable annotation syntax to do so, like so:

from typing import Dict, List

my_dict: Dict[str, Dict[str, List[str]]] = { ... }

If you're using earlier versions of Python, annotate the variable using the comment-based syntax.

Michael0x2a
  • 58,192
  • 30
  • 175
  • 224