Adding an `inspect` function to return the signature of a type?
I've been wondering whether it would make sense to have a function in `inspect` that returns the signature of a type, rather than the signature of a specific callable object. I'm not attached to any name for such a function, two ideas are `inspect.signature_of` or `inspect.signature_of_type`. ## Context: the behavior of `inspect.signature` The existing `inspect.signature` function specified in PEP 362 [0] returns the call signature of a particular object, in other words given ``` class Dog: def __init__(self, color: str): self.color = color def __call__(self, command: str): print(command) ``` we will get ```
import inspect inspect.signature(Dog) <Signature (color: str)> inspect.signature(Dog("brown")) <Signature (command: str)>
## Outline of the idea
In some cases it might be nice to be able to access the signature of an instance of `Dog` given the type `Dog`, without actually needing to instantiate it.
Moreover, there are some cases where it isn't even possible to get a callable object, but it still might be nice to have access to an `inspect.Signature` object:
- protocols cannot be instantiated. This is particularly relevant to getting Signatures because of callback protocols [1]
- typing.Callable types describe a signature, but again can't be instantiated
If if we had a function to operate on types, it would treat normal classes as if calling `inspect.signature` on the `__call__` method of an instance.
For callable types we'd want to do something similar, although this brings up some issues:
- the existing Signature requires parameter names, but a `typing.Callable` doesn't have any.
- One option would be to invent names `__0`, `__1,` etc. Otherwise we'd have to make the name optional.
- it's not obvious how to support PEP 612 ParamSpecs, and even less obvious how to support PEP 646 in full generality
I have some code snippets running through how simple cases might work, as well as the edge cases I've thought of thus far:
https://gist.github.com/stroxler/4760cbc5e49df2295cd0b524328b1c73
I'm undecided about whether the edge cases are an indication that this idea isn't worth considering.
It's worth noting that most of the edge cases involve PEP 612 / 646 generics which are pretty rare.
## Why did I start thinking about this?
In discussions of PEP 677 [2], a few folks suggested using `inspect.Signature` as inspiration for the runtime API (which we did).
This got me thinking that it might be nice for code that uses runtime types, regardless of what we decide about PEP 677, to have an API that makes accessing signature information from a type easier.
I don't personally have much need for this, but
- when I chatted with Carl Meyer from the static python team at Meta he thought it could be handy
- I could imagine it being useful for tools like ML frameworks, which I've worked on in the past, that interpret type annotations to auto-generate logic
--
[0] PEP 362 Function Signatures https://www.python.org/dev/peps/pep-0362/
[1] Callback protocols https://mypy.readthedocs.io/en/stable/protocols.html#callback-protocols
[2] PEP 677 Callable Type Syntax https://www.python.org/dev/peps/pep-0677/
participants (1)
-
Steven Troxler