Can You List the Keyword Arguments a Function Receives

Can you list the keyword arguments a function receives?

A little nicer than inspecting the code object directly and working out the variables is to use the inspect module.

>>> import inspect
>>> def func(a,b,c=42, *args, **kwargs): pass
>>> inspect.getargspec(func)
(['a', 'b', 'c'], 'args', 'kwargs', (42,))

If you want to know if its callable with a particular set of args, you need the args without a default already specified. These can be got by:

def get_required_args(func):
args, varargs, varkw, defaults = inspect.getargspec(func)
if defaults:
args = args[:-len(defaults)]
return args # *args and **kwargs are not required, so ignore them.

Then a function to tell what you are missing from your particular dict is:

def missing_args(func, argdict):
return set(get_required_args(func)).difference(argdict)

Similarly, to check for invalid args, use:

def invalid_args(func, argdict):
args, varargs, varkw, defaults = inspect.getargspec(func)
if varkw: return set() # All accepted
return set(argdict) - set(args)

And so a full test if it is callable is :

def is_callable_with_args(func, argdict):
return not missing_args(func, argdict) and not invalid_args(func, argdict)

(This is good only as far as python's arg parsing. Any runtime checks for invalid values in kwargs obviously can't be detected.)

Getting the keyword arguments actually passed to a Python method

I was inspired by lost-theory's decorator goodness, and after playing about with it for a bit came up with this:

def actual_kwargs():
"""
Decorator that provides the wrapped function with an attribute 'actual_kwargs'
containing just those keyword arguments actually passed in to the function.
"""
def decorator(function):
def inner(*args, **kwargs):
inner.actual_kwargs = kwargs
return function(*args, **kwargs)
return inner
return decorator

if __name__ == "__main__":

@actual_kwargs()
def func(msg, a=None, b=False, c='', d=0):
print msg
for arg, val in sorted(func.actual_kwargs.iteritems()):
print ' %s: %s' % (arg, val)

func("I'm only passing a", a='a')
func("Here's b and c", b=True, c='c')
func("All defaults", a=None, b=False, c='', d=0)
func("Nothin'")
try:
func("Invalid kwarg", e="bogon")
except TypeError, err:
print 'Invalid kwarg\n %s' % err

Which prints this:


I'm only passing a
a: a
Here's b and c
b: True
c: c
All defaults
a: None
b: False
c:
d: 0
Nothin'
Invalid kwarg
func() got an unexpected keyword argument 'e'

I'm happy with this. A more flexible approach is to pass the name of the attribute you want to use to the decorator, instead of hard-coding it to 'actual_kwargs', but this is the simplest approach that illustrates the solution.

Mmm, Python is tasty.

How to get keyword arguments for a function

You can use inspect.getargspec() to get the arguments a function expects.

>>> inspect.getargspec(test)
ArgSpec(args=['arg1', 'arg2', 'arg3'], varargs=None, keywords=None,
defaults=(None,))

As you can see the keywords attribute is None as any argument can be passed as a kwarg; it would contain the name of the **kwargs argument if one existed.

To get a dict mapping the argument names to default values you can use this code with as being the ArgSpec returned by inspect.getargspec():

defaults = dict(zip(*[reversed(l) for l in (as.args, as.defaults or [])]))

Get Keyword Arguments for Function, Python

Do you want something like this:

>>> def func(x,y,z,a=1,b=2,c=3):
pass

>>> func.func_code.co_varnames[-len(func.func_defaults):]
('a', 'b', 'c')

How can I pass keyword arguments as parameters to a function?

Looks like you're looking for the * and ** notations:

def outer_func(*args, **kwargs):
inner_func(*args, **kwargs)

Then you can do outer_func(1, 2, 3, a='x', b='y'), and outer_func will call inner_func(1, 2, 3, a='x', b='y').

If you only want to allow keyword arguments, drop the *args.


In a function definition, a parameter marked with * receives a tuple of all positional arguments that didn't correspond to other declared parameters, and an argument marked with ** receives a dict of all keyword arguments that didn't correspond to other declared parameters.

In a function call, prefixing a sequence (or other iterable) argument with * unpacks it into separate positional arguments, and prefixing a mapping argument with ** unpacks it into separate keyword arguments.

What is the purpose and use of **kwargs?

You can use **kwargs to let your functions take an arbitrary number of keyword arguments ("kwargs" means "keyword arguments"):

>>> def print_keyword_args(**kwargs):
... # kwargs is a dict of the keyword args passed to the function
... for key, value in kwargs.iteritems():
... print "%s = %s" % (key, value)
...
>>> print_keyword_args(first_name="John", last_name="Doe")
first_name = John
last_name = Doe

You can also use the **kwargs syntax when calling functions by constructing a dictionary of keyword arguments and passing it to your function:

>>> kwargs = {'first_name': 'Bobby', 'last_name': 'Smith'}
>>> print_keyword_args(**kwargs)
first_name = Bobby
last_name = Smith

The Python Tutorial contains a good explanation of how it works, along with some nice examples.

Python 3 update

For Python 3, instead of iteritems(), use items()

Passing a list of kwargs?

Yes. You do it like this:

def method(**kwargs):
print kwargs

keywords = {'keyword1': 'foo', 'keyword2': 'bar'}
method(keyword1='foo', keyword2='bar')
method(**keywords)

Running this in Python confirms these produce identical results:

{'keyword2': 'bar', 'keyword1': 'foo'}
{'keyword2': 'bar', 'keyword1': 'foo'}

Passing a dictionary to a function as keyword parameters

Figured it out for myself in the end. It is simple, I was just missing the ** operator to unpack the dictionary

So my example becomes:

d = dict(p1=1, p2=2)
def f2(p1,p2):
print p1, p2
f2(**d)

How to check which arguments a function/method takes?

You can use inspect.getargspec() to see what arguments are accepted, and any default values for keyword arguments.

Demo:

>>> def foo(bar, baz, spam='eggs', **kw): pass
...
>>> import inspect
>>> inspect.getargspec(foo)
ArgSpec(args=['bar', 'baz', 'spam'], varargs=None, keywords='kw', defaults=('eggs',))
>>> inspect.getargspec(foo).args
['bar', 'baz', 'spam']

In Python 3, you want to use inspect.getfullargspec() as this method supports new Python 3 function argument features:

>>> def foo(bar: str, baz: list, spam: str = 'eggs', *, monty: str = 'python', **kw) -> None: pass
...
>>> import inspect
>>> inspect.getfullargspec(foo)
FullArgSpec(args=['bar', 'baz', 'spam'], varargs=None, varkw='kw', defaults=('eggs',), kwonlyargs=['monty'], kwonlydefaults={'monty': 'python'}, annotations={'baz': <class 'list'>, 'return': None, 'spam': <class 'str'>, 'monty': <class 'str'>, 'bar': <class 'str'>})

inspect.getargspec() should be considered deprecated in Python 3.

Python 3.4 adds the inspect.Signature() object:

>>> inspect.signature(foo)
<inspect.Signature object at 0x100bda588>
>>> str(inspect.signature(foo))
"(bar:str, baz:list, spam:str='eggs', *, monty:str='python', **kw) -> None"
>>> inspect.signature(foo).parameters
mappingproxy(OrderedDict([('bar', <Parameter at 0x100bd67c8 'bar'>), ('baz', <Parameter at 0x100bd6ea8 'baz'>), ('spam', <Parameter at 0x100bd69f8 'spam'>), ('monty', <Parameter at 0x100bd6c28 'monty'>), ('kw', <Parameter at 0x100bd6548 'kw'>)]))

and many more interesting options to play with signatures.



Related Topics



Leave a reply



Submit