On Fri, Sep 4, 2020 at 12:14 AM Никита Соболев <n.a.sobolev@gmail.com> wrote:
> Though I wonder how to represent `Union[bytes, str]?` using the | syntax.  `(bytes | str)?` or `bytes? | str?`

Good question! From the theoretical point of view, all your examples should be equal.
Since Union always maintains its structure.

Currently, it works correctly:

```
from typing import Optional, Union

x: Optional[Union[int, str]]
y: Union[Optional[int], Optional[str]]

reveal_type(x)  # Union[builtins.int, builtins.str, None]
reveal_type(y)  # Union[builtins.int, None, builtins.str, None]
```

However, mypy can possibly flatten repeating `None` values, but that's another topic.

I know they are equivalent and can both be used. My question (which you didn't answer) is which variant should we recommend, and why? I honestly find both `(bytes | str)?` and `bytes? | str?` unpleasant to look at, and the fact that it's not clear which is better makes it even worse. We could even recommend `bytes | str?` but that's even weirder.

In contrast, if we don't introduce `?`, then `bytes | str | None` is clear and looks more readable to me; and there's no other variant (you could argue about `None | bytes | str` but that's of the same order as whether to write `bytes | str` or `str | bytes`).

All of which IMO is a ding against adding `?`.
 
--
--Guido van Rossum (python.org/~guido)