'or' for Union types

Someone in my firm asked “is it ok to annotate a function like this?”

def foo(var: int or float or str):
    ...

Of course the answer is no. And without from __future__ import annotations this is evaluated to int which is useless.

However, in a from __future__ import annotations world this might be a viable idea. It parses already and reads very nicely!

I prefer the above example to

from typing import Union

def foo(var: Union[int, float, str]):
    ...

and I even prefer

def foo(x: int or None):

to

from typing import Optional

def foo(x: Optional[int]):

I start to dislike it when the union gets huge:

x: int or float or bool or complex or Decimal

vs

x: Union[int, float, bool, complex, Decimal]

Although again I strongly prefer

x: Union[int, float, bool, complex, Decimal] or None

to

x: Optional[Union[int, float, bool, complex, Decimal]]

or worse

x: Union[int, float, bool, complex, Decimal, None]

I think a few things recommend this:

  • It eliminates a common typing import.
  • Slightly reduces line length until the union is 5 types or more.
  • The spacing and reduced amount of surrounding [] symbols makes each type more legible, not to mention that many existing syntax highlighters will pick out the or and the type names in different font colours/styles.
  • Sphinx already supports equivalent syntax - see ‘Multiple types in a type field will be linked automatically if separated by the word “or”’.
  • It is more natural to read and say out loud.

Using this syntax would present compatibility issues while Python versions with evaluated annotations remain a thing, so maybe it’s a longer range idea, unless linters could help mitigate those issues.

2 Likes

Someone in my firm asked “is it ok to annotate a function like this?”

def foo(var: int or float or str):

...

This is a common error, not just in annotations. Many beginners want to

write:

if string == "cat" or "dog":

    ...

or similar constucts. Of course it doesn’t do what they expect. Python

reads almost like English, but it’s not precisely English, and this is

one of those differences.

[…]

However, in a from __future__ import annotations world this might be

a viable idea. It parses already and reads very nicely!

Indeed it does read very nicely, if you’re used to English, but please

don’t introduce this difference between annotations and regular Python

expressions. Its hard enough for people to avoid this “or” trap without

having or behave differently in annotations and other expressions.

"Why does ``cat or dog`` behave completely differently 

to ``Cat or Dog`` in annotations?"
3 Likes

In the case of if string == "cat" or "dog", it can be somewhat translated to an English equivalent through the usage of if string in ("cat", "dog"). Is there an equivalent of sorts which already exists for annotations?