1

In Python, types are first class objects. As such, I can create a dictionary with types as the keys. For example:

mydict = {
    int: "Hello!",
    str: 12,
    SomeClassName: "Hello again!"}

Assuming that my dictionary will be populated with arbitrary types as keys, how do I type annotate that?

I've tried:

mydict: dict[type, Any] = {
    int: "Hello!",
    str: 12,
    SomeClassName: "Hello again!"}

and:

mydict: dict[Type[Any], Any] = {
    int: "Hello!",
    str: 12,
    SomeClassName: "Hello again!"}

and even:

mydict: dict[Any, Any] = {
    int: "Hello!",
    str: 12,
    SomeClassName: "Hello again!"}

But mypy complains about the assignment for all of those. What is the proper way to type annotate a dictionary that takes any type as a key?

If I had just certain types like int and str, I could probably annotate it as dict[Union[Type[int], Type[str]]], Any] but since I want to support keys of any type, that just doesn't cut it.

Without the type annotation, the syntax works fine and I can even retrieve specific values from the dictionary. For example:

mydict = {
    int: "Hello!",
    str: 12,
    SomeClassName: "Hello again!"}

print(mydict[int])

...and it succesfully prints out Hello!

If it matters any, I'm using Python 3.9.6 and mypy 0.812.

buhtz
  • 10,774
  • 18
  • 76
  • 149
Eric Evans
  • 94
  • 10

1 Answers1

2

@Heike was nice enough to give me my answer as a comment. (THANK YOU!)

To type annotate a dictionary that uses types as the keys, use Dict...not dict:

mydict: Dict[type, Any]

...works great. This was a silly mistake on my part stemming from me initially trying to type annotate an OrderedDict. Type annotating an OrderedDict in the same fashion:

mydict: OrderedDict[type, Any] = {int: "Something"}

...does not work. However, I have done enough reading about dicts over the last 24 hours while trying to spot my mistake that I also spotted that I had attempted to assign a dict to an OrderedDict which also doesn't work.

Thank you Heike for pointing out my obvious mistake.

Eric Evans
  • 94
  • 10
  • Possibly also `Type` rather than `type`? – Jiří Baum Aug 02 '21 at 08:10
  • 1
    @sabik, Nope. Type requires that the specific type is specified such as ```Type[int]``` which wouldn't work for my purposes since I wanted it to accept any type. I assumed the same which is how I found it didn't work that way. Use ```type``` to annotate something that accepts any type...but I do appreciate your comment. – Eric Evans Aug 02 '21 at 08:23
  • Parameterising lowercase `dict` should also be fine in python 3.9+ btw — it's only in python <=3.8 where you have to use the uppercase aliases from the typing module for `dict`, `list`, etc. See https://www.python.org/dev/peps/pep-0585/ and https://mypy-play.net/?mypy=latest&python=3.9&gist=3a3cfbf6868ca0c0240f8889dbe544db. (Also, mark your question as closed if you've found a solution to your problem! :) ) – Alex Waygood Aug 02 '21 at 12:00
  • 1
    @AlexWaygood, it SHOULD be fine...but mypy wasn't liking it. However, today I pulled up that previous version of my code and mypy is no longer complaining about it even though I haven't changed the code or modified the virtualenv or its packages in any way. Strange. I have no clue. Thank you for looking at it. – Eric Evans Aug 02 '21 at 23:53
  • 1
    @AlexWaygood. As for closing the question, StackOverflow won't allow me to accept my solution until tomorrow and the only other option is deleting the question which is frowned upon. – Eric Evans Aug 02 '21 at 23:57
  • @EricEvans fair enough on all counts! I've also had annoying issues regarding getting MyPy to accept python 3.9 features, which have usually turned out to be to do with having multiple versions of mypy installed... – Alex Waygood Aug 03 '21 at 09:34