You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Question about the representation of ParamSpec Generic classes #1274
While working on PEP 696 (TypeVarLike defaults) one point I've been particularly confused about how was the types that should be used for Generics with ParamSpecs in __parameters__ subscription.
Should you pass a list to the list as suggested in the PEP, types.GenericAlias and by mypy
classX(Generic[P]): ...
# from pep 612deff(x: X[[int, bool]]) ->str: ...
reveal_type(X[[int, bool]]()) # mypy: revealed type is __main__.X[[builtins.int, builtins.bool]]# using types.GenericAliasclassX_types:
__class_getitem__=classmethod(types.GenericAlias)
reveal_type(X_types[[int, bool]]) # runtime: X_types[[<class 'int'>, <class 'bool'>]]reveal_type(X_types[(int, bool)]) # runtime: X_types[<class 'int'>, <class 'bool'>]
or use a tuple as the typing runtime suggests and by pyright
reveal_type(X[[int, bool]]) # runtime: revealed type is X[(<class 'int'>, <class 'bool'>)]reveal_type(X[[int, bool]]) # pyright: revealed type is type[X[(int, bool)]]
This may seem relatively inconsequential and at runtime it probably is but after talking to @erictraut he brought up that PEP 696 supports both lists and tuples as the defaults for ParamSpec (https://peps.python.org/pep-0696/#paramspec-defaults) and this will be harder to support in pyright but I'd really like symmetry with the type of default and the type that you should pass to a subscription. Ideally I think I tuples would be the best type for for default just cause they should be the easiest to analyse and they are the closest in style to a PEP 677 (Callable Type Syntax) syntax even if the current syntax does look more like Callable's current syntax. Does anyone from the pyre team or from mypy have any particular opposition to changing to just supporting tuples in default?
I think a list representation is more consistent with the text of PEP 612 and the runtime representation of Callable. We should change the runtime repr of ParamSpec generics to be more like Callable, because right now they're inconsistent:
IIRC there was a specific reason to use a list for ParamSpec. The runtime cannot tell the difference between X[Y, Z] and X[(Y, Z)] (this is independent of the type of X -- it's a general problem with __getitem__).
To avoid this ambiguity I recommend using a list, as Jelle wrote.
Activity
JelleZijlstra commentedon Oct 24, 2022
I think a list representation is more consistent with the text of PEP 612 and the runtime representation of Callable. We should change the runtime repr of ParamSpec generics to be more like Callable, because right now they're inconsistent:
gvanrossum commentedon Nov 4, 2022
IIRC there was a specific reason to use a list for
ParamSpec. The runtime cannot tell the difference betweenX[Y, Z]andX[(Y, Z)](this is independent of the type of X -- it's a general problem with__getitem__).To avoid this ambiguity I recommend using a list, as Jelle wrote.
Gobot1234 commentedon Mar 12, 2023
This has been changed as of python/peps#3052. I'll create an issue for the internal representations of these classes on cpython.
jeffbrown7816-collab commentedon Oct 12, 2025
#2099