You can use either the inspect.signature()
or inspect.getfullargspec()
functions:
import inspect
argspec = inspect.getfullargspec(somefunction)
signature = inspect.signature(somefunction)
inspect.fullargspec
returns a named tuple with 7 elements:
- A list with the argument names
- The name of the catchall
*args
parameter, if defined (None
otherwise)
- The name of the catchall
**kwargs
parameter, if defined (None
otherwise)
- A tuple with default values for the keyword arguments; they go with the last elements of the arguments; match these by length of the default values tuple.
- A list of keyword-only parameter names
- A dictionary of default values for the keyword-only parameter names, if any
- and a dictionary containing the annotations
With inspect.signature()
you get a Signature
object, a rich object that models not only the above data as a more structured set of objects but also lets you bind values to parameters the same way a call to the function would.
Which one is better will depend on your use cases.
Demo:
>>> import inspect
>>> def foo(bar, baz, spam='eggs', *monty, python: "kwonly", spanish=42, **inquisition) -> "return annotation":
... pass
...
>>> inspect.getfullargspec(foo)
FullArgSpec(args=['bar', 'baz', 'spam'], varargs='monty', varkw='inquisition', defaults=('eggs',), kwonlyargs=['python', 'spanish'], kwonlydefaults={'spanish': 42}, annotations={'return': 'return annotation', 'python': 'kwonly'})
>>> signature = inspect.signature(foo)
>>> signature
<Signature (bar, baz, spam='eggs', *monty, python: 'kwonly', spanish=42, **inquisition) -> 'return annotation'>
>>> signature.parameters['python'].kind.description
'keyword-only'
>>> signature.bind('Eric', 'Idle', 'John', python='Cleese')
<BoundArguments (bar='Eric', baz='Idle', spam='John', python='Cleese')>
If you have a dictionary named values
of possible parameter values, I'd use inspect.signature()
and use the Signature.parameters
mapping to match names:
posargs = [
values[param.name]
for param in signature.parameters.values()
if param.kind is Parameter.POSITIONAL_ONLY
]
skip_kinds = {Parameter.POSITIONAL_ONLY, Parameter.VAR_POSITIONAL, Parameter.VAR_KEYWORD}
kwargs = {
param.name: values[param.name]
for param in signature.parameters.values()
if param.name in values and param.kind not in skip_kinds
}
The above gives you a list of values for the positional-only parameters, and a dictionary for the rest (excepting any *args
or **kwargs
parameters).
inspect.signature()
was introduced in Python 3.3, so it wasn't available at the time this question was made. But nowadays, this is likely the best solution, because it also returns the annotations/expected types of the arguments if available: docs.python.org/3/library/inspect.html - so for modern pythonistas, please consider this answer instead of the old accepted one. – Smoothbore