Skip to content

How to Check If a Function Accepts Certain Arguments in Python

Learn how to validate Python function arguments at runtime using inspect.signature() to check parameter names, defaults, and **kwargs before calling, avoiding TypeError.

In dynamic Python applications (such as plugin systems, decorators, or frameworks) you often need to determine programmatically whether a specific function accepts certain arguments before calling it. Calling a function with unexpected arguments results in a TypeError.

This guide explores how to inspect function signatures using the standard inspect module to validate parameters, check for default values, and safely handle argument passing.

Understanding Function Signatures

A function signature defines the inputs (parameters) and output (return annotation) of a function. Python's inspect module allows you to access this metadata at runtime.

A signature object contains a collection of Parameters, which hold vital details:

  • Name: The name of the argument (e.g., x, user_id).
  • Default: The default value if one exists (or inspect._empty).
  • Kind: How the argument can be passed (Positional, Keyword, *args, **kwargs).
  • Annotation: Type hints (e.g., int, str).

The most robust way to analyze arguments is by retrieving the Signature object. This allows you to view all expected parameters.

import inspect

def calculate_total(price: float, tax: float = 0.05) -> float:
    return price * (1 + tax)

sig = inspect.signature(calculate_total)

print(f"Function Signature: {sig}")

for name, param in sig.parameters.items():
    print(f"Name: {name}, Default: {param.default}, Annotation: {param.annotation}")

Output:

Function Signature: (price: float, tax: float = 0.05) -> float
Name: price, Default: <class 'inspect._empty'>, Annotation: <class 'float'>
Name: tax, Default: 0.05, Annotation: <class 'float'>

Method 2: Checking for Specific Parameter Names

If you simply need to know, "Does this function accept an argument named user_id?", you can check for membership in the parameters dictionary.

Checking for Exact Arguments

import inspect

def send_email(email, subject, body):
    pass

def send_sms(phone, message):
    pass

def has_argument(func, arg_name):
    sig = inspect.signature(func)
    return arg_name in sig.parameters

print(f"send_email accepts 'email'? {has_argument(send_email, 'email')}")
print(f"send_sms accepts 'email'?   {has_argument(send_sms, 'email')}")

Output:

send_email accepts 'email'? True
send_sms accepts 'email'?   False

Handling **kwargs

A function might not explicitly name an argument but still accept it via **kwargs (variable keyword arguments). You should check for VAR_KEYWORD if you want to be strictly accurate about what can be passed.

import inspect

def dynamic_func(a, **kwargs):
    pass

sig = inspect.signature(dynamic_func)
params = sig.parameters

arg_name = "random_arg"

accepts_arg = (arg_name in params) or \
              any(p.kind == p.VAR_KEYWORD for p in params.values())

print(f"dynamic_func accepts '{arg_name}'? {accepts_arg}")

Output:

dynamic_func accepts 'random_arg'? True

Method 3: Runtime Checking with try-except

Sometimes, introspection is unnecessary overhead. The Pythonic "Easier to Ask for Forgiveness than Permission" (EAFP) approach involves trying to call the function and catching the TypeError if the arguments don't match.

This is useful when you are ready to execute the function immediately.

def add_numbers(x, y):
    return x + y

try:
    add_numbers(x=5, y=10, z=15)
except TypeError as e:
    print(f"Call failed: {e}")

try:
    result = add_numbers(5, 10)
    print(f"Result: {result}")
except TypeError as e:
    print(f"Error: {e}")

Output:

Call failed: add_numbers() got an unexpected keyword argument 'z'
Result: 15

Conclusion

To check if a function accepts certain arguments:

  1. Use inspect.signature(func) for static analysis or validation logic. It is the most accurate and safe method.
  2. Check sig.parameters keys to see if specific argument names exist.
  3. Check for VAR_KEYWORD (**kwargs) if you need to support dynamic arguments.
  4. Use try-except TypeError if you simply want to call the function and handle mismatches at runtime.
Navigation