2

I'm trying to understand how to use Python 3.9 type hint to annotate a function that receives a dict with optional or multiple type values. I know that with Typing module, I can use easily Union and Optional. But I'd like to know if it is possible to achieve that using only Python 3.9 annotations. I didn't found anything on this matter on PEP 585.

Reference: How should I use the Optional type hint?

Example:

From Typing import Dict, Optional, Union

def foo(bar: Dict[Union[str, int], Optional[str]]) -> bool: return True

Should I do instead:

from __future__ import annotations

def foo(bar: dict[[str, int], [str, None]) -> bool: return True
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Kfcaio
  • 442
  • 1
  • 8
  • 20
  • 1
    Can't you just use `dict` instead of `Dict`? – timgeb Jun 24 '20 at 16:06
  • Yes, I can use ```dict[str, Optional[str]]```. But I'd like to know if there is any way to use ```dict``` container, without ```Typing.Optional``` or ```Typing.Union``` , for annotating keys and values. – Kfcaio Jun 24 '20 at 16:12
  • no, `Union` or `Optional` are not standard collections. – timgeb Jun 24 '20 at 16:18
  • Yes, I know. I mean, ```dict[str, Typing.Optional[str]]```. I'd like to know if I can achieve the same without using Typing in Python 3.9 – Kfcaio Jun 24 '20 at 16:20
  • 1
    no, you can't, because `Union` and `Optional` are not standard collections. – timgeb Jun 24 '20 at 16:29
  • Given ```def foo(a: dict[str, Optional[str]]): return True```, one have ```foo.__annotations__ == {'a': 'dict[str, Optional[str]]'}``` which evaluates to True – Kfcaio Jun 24 '20 at 16:37

2 Answers2

5

No; the enhancements to type annotations in Python 3.9 do not include making Optional or Union builtins. You'll still need to import those from typing.

As of Python 3.10, you can use the | operator to indicate a union type.

If you expect the dictionary to have specific key/value types, a TypedDict that gives different types for different values is generally a better option than using tricky union types to cover all the values in any case.

Georgy
  • 12,464
  • 7
  • 65
  • 73
Samwise
  • 68,105
  • 3
  • 30
  • 44
3

In short, it depends on your linter. Visual Studio Code right now has a Python plugin v2020.11.371526539 which supports the following syntax.

from __future__ import annotations

def foo(bar: dict[str | int, str | None]) -> bool | int: 
  return True

IntelliSense displays a helpful preview: enter image description here

And also for the return type: enter image description here

For reference my selected linter is pyre-check version 857747d8246cde76501481378a6b7cf2e7072a2c and python version 3.9.0

Fred Truter
  • 667
  • 4
  • 10