How to Parse Function Signatures in Python with inspect

Extract a function's parameter names, kinds, defaults, annotations, and return type using Python's built-in inspect module.

Medium Python 3.8+ Aug 9, 2026 Functions & basics 14 views 0 copies

Python code

28 lines
Python 3.8+
import inspect

def example_function(a: int, b: str = "default", *args, c: float = 1.5, **kwargs) -> bool:
    """An example function with various parameter types."""
    return True

def parse_signature(func):
    """Parse a function's signature using the inspect module."""
    sig = inspect.signature(func)
    parameters = {}
    
    for name, param in sig.parameters.items():
        parameters[name] = {
            "kind": str(param.kind),
            "default": param.default if param.default is not inspect.Parameter.empty else None,
            "annotation": param.annotation if param.annotation is not inspect.Parameter.empty else None
        }
    
    return {
        "name": func.__name__,
        "parameters": parameters,
        "return_annotation": sig.return_annotation if sig.return_annotation is not inspect.Signature.empty else None
    }

if __name__ == "__main__":
    result = parse_signature(example_function)
    for key, value in result.items():
        print(f"{key}: {value}")

Output

stdout
name: example_function
parameters: {'a': {'kind': 'POSITIONAL_OR_KEYWORD', 'default': None, 'annotation': <class 'int'>}, 'b': {'kind': 'POSITIONAL_OR_KEYWORD', 'default': 'default', 'annotation': <class 'str'>}, 'args': {'kind': 'VAR_POSITIONAL', 'default': None, 'annotation': None}, 'c': {'kind': 'KEYWORD_ONLY', 'default': 1.5, 'annotation': <class 'float'>}, 'kwargs': {'kind': 'VAR_KEYWORD', 'default': None, 'annotation': None}}
return_annotation: <class 'bool'>

How it works

The inspect.signature call introspects a callable and returns a Signature object holding parameter metadata. Each Parameter exposes its name, kind (e.g., positional, keyword-only, varargs), default value, and type annotation. The check against inspect.Parameter.empty distinguishes a missing default or annotation from a value of None, letting you store None for absent fields. This approach works for both plain functions and methods, making it a reliable foundation for building documentation generators, argument validators, or framework introspection tools.

Common mistakes

  • Comparing defaults with `is None` instead of `is inspect.Parameter.empty`, which wrongly reports explicit `None` defaults as missing
  • Forgetting that `*args` and `**kwargs` kinds are `VAR_POSITIONAL` and `VAR_KEYWORD`, not standard parameters
  • Assuming annotations are strings — they remain actual type objects unless `from __future__ import annotations` is used
  • Not handling callables that fail `inspect.signature`, like some builtins, without wrapping in try/except

Variations

  1. Use `inspect.getfullargspec(func)` for a simpler flat list of names and defaults when you don't need annotation or kind details
  2. Call `str(sig)` directly to get a compact one-line signature like `(a: int, b: str = 'default', *args, c: float = 1.5, **kwargs) -> bool`

Real-world use cases

  • Building a CLI framework that auto-generates help text from function parameters and annotations.
  • Creating an API dispatcher that maps HTTP request fields to function arguments based on signature metadata.
  • Implementing a dependency injection container that inspects container functions to resolve required parameters automatically.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Functions & basics

Related tutorials and quizzes for this topic.