I think {int, str}, which someone proposed in one of the earlier discussions, is nice. What else would a set of types mean (unless you’re doing mathematical type theory rather than programming language typing)? But it’s unfortunate that things like isinstance and except take a tuple of types (and it has to be a tuple, not any other kind of iterable), so a set might be just as confusing for hardcore Python types as a tuple would be for polyglots.
If the compatibility issue isn’t a big deal (and I trust Guido that is isn’t), I think int | str is the best option. It’a an operator that means union, it’s used for sum/union types in other languages, it makes perfect sense if you read it as “int or str”… I cant imagine anyone being confused or put off by it.
I just realized one big advantage of `{int, str}` over `int|str`. It doesn't require adding anything to `type`, and we don't need to introduce a new lightweight builtin union type.
We could still do `~int` -- it would just return `{int, None}`. (But that *would* require adding to `type`.)
If we did this, it would behoove us to support `isinstance(x, {int, str})` as well. A wrinkle with that: the current code is naively recursive, because it's impossible to create a loop in a tuple (other than using the C API). Tuples are also easier to traverse than sets. But those are surmountable problems.
--