◐ Shell
clean mode source ↗

bpo-43224: Fix Tuple[()].__args__ by mrahtz · Pull Request #31845 · python/cpython

Here's a fun inconsistency:

>>> Tuple[()].__args__
((),)
>>> tuple[()].__args__
()

Even though there's an explicit test for the former behaviour, I don't think it's right:

  • Argument 1: If foo.__args__ is (bar,), that says that foo is being parameterised by bar. When we do Tuple[()], it's really just to get around the fact that Tuple[] is invalid syntax - what we're really meaning to say is that we're not parameterising it with anything. Tuple[()].__args__ should therefore be empty.
  • Argument 2: Everything in Tuple[...].__args__ should be a type. () is not a type.

This matters for PEP 646, where we were expecting that a TypeVarTuple with no arguments would expand to nothing rather than (). If we were to change things so it was consistent with the current behaviour of Tuple[()], we'd have

T = TypeVar('T')
Ts = TypeVarTuple('Ts')
class C(Generic[T, *Ts]): pass
Alias = C[int, *Ts]
Alias[()]  # C[int, ()]

which definitely isn't what we want.

@ilevkivskyi who added the test for the former behaviour, according to the git blame. Is there something I'm missing here?

https://bugs.python.org/issue43224