is there a way to check if a function accepts **kwargs before calling it e.g.
def FuncA(**kwargs):
print 'ok'
def FuncB(id = None):
print 'ok'
def FuncC():
print 'ok'
args = {'id': '1'}
FuncA(**args)
FuncB(**args)
FuncC(**args)
When I run this FuncA and FuncB would be okay but FuncC errors with got an unexpected keyword argument 'id' as it doesn't accept any arguments
try:
f(**kwargs)
except TypeError:
#do stuff
It's easier to ask forgiveness than permission.
def foo(a, b, **kwargs):
pass
import inspect
args, varargs, varkw, defaults = inspect.getargspec(foo)
assert(varkw=='kwargs')
This only works for Python functions. Functions defined in C extensions (and built-ins) may be tricky and sometimes interpret their arguments in quite creative ways. There's no way to reliably detect which arguments such functions expect. Refer to function's docstring and other human-readable documentation.
func is the function in question.
with python2, it's:
inspect.getargspec(func).keywords is not None
python3 is a bit tricker, following https://www.python.org/dev/peps/pep-0362/ the kind of parameter must be VAR_KEYWORD
Parameter.VAR_KEYWORD - a dict of keyword arguments that aren't bound to any other parameter. This corresponds to a "**kwargs" parameter in a Python function definition.
any(param for param in inspect.signature(func).parameters.values() if param.kind == param.VAR_KEYWORD)
For python > 3 you should to use inspect.getfullargspec.
import inspect
def foo(**bar):
pass
arg_spec = inspect.getfullargspec(foo)
assert arg_spec.varkw and arg_spec.varkw == 'bar'
Seeing that there are a multitude of different answers in this thread, I thought I would give my two cents, using inspect.signature().
Suppose you have this method:
def foo(**kwargs):
You can test if **kwargs are in this method's signature:
import inspect
sig = inspect.signature(foo)
params = sig.parameters.values()
has_kwargs = any([True for p in params if p.kind == p.VAR_KEYWORD])
More
Getting the parameters in which a method takes is also possible:
import inspect
sig = inspect.signature(foo)
params = sig.parameters.values()
for param in params:
print(param.kind)
You can also store them in a variable like so:
kinds = [param.kind for param in params]
# [<_ParameterKind.VAR_KEYWORD: 4>]
Other than just keyword arguments, there are 5 parameter kinds in total, which are as follows:
POSITIONAL_ONLY # parameters must be positional
POSITIONAL_OR_KEYWORD # parameters can be positional or keyworded (default)
VAR_POSITIONAL # *args
KEYWORD_ONLY # parameters must be keyworded
VAR_KEYWORD # **kwargs
Descriptions in the official documentation can be found here.
Examples
POSITIONAL_ONLY
def foo(a, /):
# the '/' enforces that all preceding parameters must be positional
foo(1) # valid
foo(a=1) #invalid
POSITIONAL_OR_KEYWORD
def foo(a):
# 'a' can be passed via position or keyword
# this is the default and most common parameter kind
VAR_POSITIONAL
def foo(*args):
KEYWORD_ONLY
def foo(*, a):
# the '*' enforces that all following parameters must by keyworded
foo(a=1) # valid
foo(1) # invalid
VAR_KEYWORD
def foo(**kwargs):
It appears that you want to check whether the function receives an 'id' keyword argument. You can't really do that by inspection because the function might not be a normal function, or you might have a situation like that:
def f(*args, **kwargs):
return h(*args, **kwargs)
g = lambda *a, **kw: h(*a, **kw)
def h(arg1=0, arg2=2):
pass
f(id=3) still fails
Catching TypeError as suggested is the best way to do that, but you can't really figure out what caused the TypeError. For example, this would still raise a TypeError:
def f(id=None):
return "%d" % id
f(**{'id': '5'})
And that might be an error that you want to debug. And if you're doing the check to avoid some side effects of the function, they might still be present if you catch it. For example:
class A(object):
def __init__(self): self._items = set([1,2,3])
def f(self, id): return self._items.pop() + id
a = A()
a.f(**{'id': '5'})
My suggestion is to try to identify the functions by another mechanism. For example, pass objects with methods instead of functions, and call only the objects that have a specific method. Or add a flag to the object or the function itself.
According to https://docs.python.org/2/reference/datamodel.html
you should be able to test for use of **kwargs using co_flags:
>>> def blah(a, b, kwargs):
... pass
>>> def blah2(a, b, **kwargs):
... pass
>>> (blah.func_code.co_flags & 0x08) != 0
False
>>> (blah2.func_code.co_flags & 0x08) != 0
True
Though, as noted in the reference this may change in the future, so I would definitely advise to be extra careful. Definitely add some unit tests to check this feature is still in place.
Related
Let's consider a function that accepts multiple arguments as under:
def my_function(*args):
my_list = []
for _ in args:
my_list.append(_)
another_function(my_list)
Now, the issue that I face in my scenario is that: I need my_list to contain at least one value, any argument, but at least one.
A user can do my_function(arg1), my_fuynction(arg1,arg2), my_function(arg1,arg2,arg3) and so on. But if a user does my_function(), I need to provide a default argument (say arg1) to the function.
If I put an default argument, then the argument defaultarg will be compulsory and it has to be supplied with some value:
def my_function(defaultarg, *args):
#function
If I put it as optional argument, then I will have to provide a default value to the argument:
def my_function(optionalarg = defaultvalue, *args):
#function
Both these ways do not work for me as I can't make it compulsory and I can't give a default value for it.
How do I create this function so that if no arguments are passed, the function assumes one argument to have been passed?
As of now, I am handling this by putting a if...else in the function as under:
def my_function(*args):
my_list = []
if len(args) == 0:
my_list.append('defaultarg')
else:
for _ in args:
my_list.append(_)
another_function(my_list)
Is there any better way to do this?
I can't give a default value for it
I don't understand this part of your question. You are providing the default value 'defaultarg' in your own solution?! My answer assumes that you can get the default value from somewhere.
Anyway, if you want to keep the f(*args) signature, you can check whether the args tuple is empty and supply a default value.
def my_function(*args):
if not args:
args = (default_value,)
# more code
or
def my_function(*args):
if not args:
return my_function(default_value)
# more code
You won't get around explicitly checking whether args is empty, but maybe you'll like one of these proposals better than your version.
edit:
You could also write a parameterized decorator.
def with_default_value(default_value):
def with_default_value_decorator(f):
def f_new(*args):
if not args:
return f(default_value)
return f(*args)
return f_new
return with_default_value_decorator
Example:
#with_default_value('hi')
def my_print(*args):
print(' '.join(args))
Demo:
>>> my_print('hello', 'world')
hello world
>>> my_print()
hi
I know how to pass a function as argument, and then use the function later. However I could not figure out how to do this with a method. I'd like to provide users with an "API" that allows them to configure custom functions.
As a (not) working example, let's say I want the user to be able to supply some general pandas function:
import pandas as pd
# user-supplied data
right = pd.DataFrame({'right_a':[1,2],
'right_b':[3,4]})
# user-supplied function & arguments
myfun = pd.DataFrame.merge
args = {'right':right,
'right_on':'right_a',
'how':'inner'
}
user_configs = {'func': myfun,
'args':args}
def exec_func(exec_dict):
# some data that only the function knows:
left = pd.DataFrame({'left_a':[1,2],'left_b':['foo','bar']})
# some args that only the function knows
exec_dict['args']['left_on'] = 'left_a'
# apply the function
#result = left.merge(**exec_dict['args']) # desired result
result = left.exec_dict['func'](**exec_dict['args']) # generalized but not working code
return result
exec_func(user_configs)
the above code result in a
AttributeError: 'DataFrame' object has no attribute 'exec_dict'
for obvious reasons. How could i achieve the desired behavior, that allows the user to supply different functions?
So I have simplified your problem a little and omitted pandas. The way to go about calling a method of an instance by name is via the getattribute method:
class MethodProvider (object):
def __init__(self):
pass
def method1(self, foo):
print('Method1 was called with arguments %s'%foo)
def method2(self, baz):
print('Method2 was called with argument %s'%baz)
def exec_method(obj, meth, kwargs):
func = obj.__getattribute__(meth)
func(**kwargs)
# Test construction
mp = MethodProvider()
exec_method(
mp,
'method1',
{'foo': 'bar'}
)
exec_method(
mp,
'method2',
{'baz': 'buzz'}
)
Methods are, loosely speaking, functions that receive the instance as the first argument. exec_dict['func'] already is the method, it does not need to be looked up on left. Simply pass left as the first argument.
# |method/function|| called with... |
result = exec_dict['func'](left, **exec_dict['args'])
# | instance
# | further arguments
This code works for any callable that takes the dataframe left as its first argument, not just dataframe methods.
Instead of expecting func and args wrapped in a dictionary, exec_func can directly receive them. left_on can also be passed directly.
def exec_func(func, **args):
left = pd.DataFrame({'left_a':[1,2],'left_b':['foo','bar']})
# apply the function
result = func(left, left_on='left_a', **args)
return result
exec_func(**user_configs)
Note that it is customary to use args for positional and kwargs for keyword arguments/parameters, i.e. def exec_func(func, *args, **kwargs): ....
This question already has answers here:
What does ** (double star/asterisk) and * (star/asterisk) do for parameters?
(25 answers)
Closed 9 years ago.
So I have difficulty with the concept of *args and **kwargs.
So far I have learned that:
*args = list of arguments - as positional arguments
**kwargs = dictionary - whose keys become separate keyword arguments and the values become values of these arguments.
I don't understand what programming task this would be helpful for.
Maybe:
I think to enter lists and dictionaries as arguments of a function AND at the same time as a wildcard, so I can pass ANY argument?
Is there a simple example to explain how *args and **kwargs are used?
Also the tutorial I found used just the "*" and a variable name.
Are *args and **kwargs just placeholders or do you use exactly *args and **kwargs in the code?
The syntax is the * and **. The names *args and **kwargs are only by convention but there's no hard requirement to use them.
You would use *args when you're not sure how many arguments might be passed to your function, i.e. it allows you pass an arbitrary number of arguments to your function. For example:
>>> def print_everything(*args):
for count, thing in enumerate(args):
... print( '{0}. {1}'.format(count, thing))
...
>>> print_everything('apple', 'banana', 'cabbage')
0. apple
1. banana
2. cabbage
Similarly, **kwargs allows you to handle named arguments that you have not defined in advance:
>>> def table_things(**kwargs):
... for name, value in kwargs.items():
... print( '{0} = {1}'.format(name, value))
...
>>> table_things(apple = 'fruit', cabbage = 'vegetable')
cabbage = vegetable
apple = fruit
You can use these along with named arguments too. The explicit arguments get values first and then everything else is passed to *args and **kwargs. The named arguments come first in the list. For example:
def table_things(titlestring, **kwargs)
You can also use both in the same function definition but *args must occur before **kwargs.
You can also use the * and ** syntax when calling a function. For example:
>>> def print_three_things(a, b, c):
... print( 'a = {0}, b = {1}, c = {2}'.format(a,b,c))
...
>>> mylist = ['aardvark', 'baboon', 'cat']
>>> print_three_things(*mylist)
a = aardvark, b = baboon, c = cat
As you can see in this case it takes the list (or tuple) of items and unpacks it. By this it matches them to the arguments in the function. Of course, you could have a * both in the function definition and in the function call.
One place where the use of *args and **kwargs is quite useful is for subclassing.
class Foo(object):
def __init__(self, value1, value2):
# do something with the values
print value1, value2
class MyFoo(Foo):
def __init__(self, *args, **kwargs):
# do something else, don't care about the args
print 'myfoo'
super(MyFoo, self).__init__(*args, **kwargs)
This way you can extend the behaviour of the Foo class, without having to know too much about Foo. This can be quite convenient if you are programming to an API which might change. MyFoo just passes all arguments to the Foo class.
Here's an example that uses 3 different types of parameters.
def func(required_arg, *args, **kwargs):
# required_arg is a positional-only parameter.
print required_arg
# args is a tuple of positional arguments,
# because the parameter name has * prepended.
if args: # If args is not empty.
print args
# kwargs is a dictionary of keyword arguments,
# because the parameter name has ** prepended.
if kwargs: # If kwargs is not empty.
print kwargs
>>> func()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: func() takes at least 1 argument (0 given)
>>> func("required argument")
required argument
>>> func("required argument", 1, 2, '3')
required argument
(1, 2, '3')
>>> func("required argument", 1, 2, '3', keyword1=4, keyword2="foo")
required argument
(1, 2, '3')
{'keyword2': 'foo', 'keyword1': 4}
Here's one of my favorite places to use the ** syntax as in Dave Webb's final example:
mynum = 1000
mystr = 'Hello World!'
print("{mystr} New-style formatting is {mynum}x more fun!".format(**locals()))
I'm not sure if it's terribly fast when compared to just using the names themselves, but it's a lot easier to type!
One case where *args and **kwargs are useful is when writing wrapper functions (such as decorators) that need to be able accept arbitrary arguments to pass through to the function being wrapped. For example, a simple decorator that prints the arguments and return value of the function being wrapped:
def mydecorator( f ):
#functools.wraps( f )
def wrapper( *args, **kwargs ):
print "Calling f", args, kwargs
v = f( *args, **kwargs )
print "f returned", v
return v
return wrapper
*args and **kwargs are special-magic features of Python.
Think of a function that could have an unknown number of arguments. For example, for whatever reasons, you want to have function that sums an unknown number of numbers (and you don't want to use the built-in sum function). So you write this function:
def sumFunction(*args):
result = 0
for x in args:
result += x
return result
and use it like: sumFunction(3,4,6,3,6,8,9).
**kwargs has a diffrent function. With **kwargs you can give arbitrary keyword arguments to a function and you can access them as a dictonary.
def someFunction(**kwargs):
if 'text' in kwargs:
print kwargs['text']
Calling someFunction(text="foo") will print foo.
Just imagine you have a function but you don't want to restrict the number of parameter it takes.
Example:
>>> import operator
>>> def multiply(*args):
... return reduce(operator.mul, args)
Then you use this function like:
>>> multiply(1,2,3)
6
or
>>> numbers = [1,2,3]
>>> multiply(*numbers)
6
The names *args and **kwargs or **kw are purely by convention. It makes it easier for us to read each other's code
One place it is handy is when using the struct module
struct.unpack() returns a tuple whereas struct.pack() uses a variable number of arguments. When manipulating data it is convenient to be able to pass a tuple to struck.pack() eg.
tuple_of_data = struct.unpack(format_str, data)
# ... manipulate the data
new_data = struct.pack(format_str, *tuple_of_data)
without this ability you would be forced to write
new_data = struct.pack(format_str, tuple_of_data[0], tuple_of_data[1], tuple_of_data[2],...)
which also means the if the format_str changes and the size of the tuple changes, I'll have to go back and edit that really long line
Note that *args/**kwargs is part of function-calling syntax, and not really an operator. This has a particular side effect that I ran into, which is that you can't use *args expansion with the print statement, since print is not a function.
This seems reasonable:
def myprint(*args):
print *args
Unfortunately it doesn't compile (syntax error).
This compiles:
def myprint(*args):
print args
But prints the arguments as a tuple, which isn't what we want.
This is the solution I settled on:
def myprint(*args):
for arg in args:
print arg,
print
These parameters are typically used for proxy functions, so the proxy can pass any input parameter to the target function.
def foo(bar=2, baz=5):
print bar, baz
def proxy(x, *args, **kwargs): # reqire parameter x and accept any number of additional arguments
print x
foo(*args, **kwargs) # applies the "non-x" parameter to foo
proxy(23, 5, baz='foo') # calls foo with bar=5 and baz=foo
proxy(6)# calls foo with its default arguments
proxy(7, bar='asdas') # calls foo with bar='asdas' and leave baz default argument
But since these parameters hide the actual parameter names, it is better to avoid them.
You can have a look at python docs (docs.python.org in the FAQ), but more specifically for a good explanation the mysterious miss args and mister kwargs (courtesy of archive.org) (the original, dead link is here).
In a nutshell, both are used when optional parameters to a function or method are used.
As Dave says, *args is used when you don't know how many arguments may be passed, and **kwargs when you want to handle parameters specified by name and value as in:
myfunction(myarg=1)
This question already has answers here:
What does ** (double star/asterisk) and * (star/asterisk) do for parameters?
(25 answers)
Closed 9 years ago.
So I have difficulty with the concept of *args and **kwargs.
So far I have learned that:
*args = list of arguments - as positional arguments
**kwargs = dictionary - whose keys become separate keyword arguments and the values become values of these arguments.
I don't understand what programming task this would be helpful for.
Maybe:
I think to enter lists and dictionaries as arguments of a function AND at the same time as a wildcard, so I can pass ANY argument?
Is there a simple example to explain how *args and **kwargs are used?
Also the tutorial I found used just the "*" and a variable name.
Are *args and **kwargs just placeholders or do you use exactly *args and **kwargs in the code?
The syntax is the * and **. The names *args and **kwargs are only by convention but there's no hard requirement to use them.
You would use *args when you're not sure how many arguments might be passed to your function, i.e. it allows you pass an arbitrary number of arguments to your function. For example:
>>> def print_everything(*args):
for count, thing in enumerate(args):
... print( '{0}. {1}'.format(count, thing))
...
>>> print_everything('apple', 'banana', 'cabbage')
0. apple
1. banana
2. cabbage
Similarly, **kwargs allows you to handle named arguments that you have not defined in advance:
>>> def table_things(**kwargs):
... for name, value in kwargs.items():
... print( '{0} = {1}'.format(name, value))
...
>>> table_things(apple = 'fruit', cabbage = 'vegetable')
cabbage = vegetable
apple = fruit
You can use these along with named arguments too. The explicit arguments get values first and then everything else is passed to *args and **kwargs. The named arguments come first in the list. For example:
def table_things(titlestring, **kwargs)
You can also use both in the same function definition but *args must occur before **kwargs.
You can also use the * and ** syntax when calling a function. For example:
>>> def print_three_things(a, b, c):
... print( 'a = {0}, b = {1}, c = {2}'.format(a,b,c))
...
>>> mylist = ['aardvark', 'baboon', 'cat']
>>> print_three_things(*mylist)
a = aardvark, b = baboon, c = cat
As you can see in this case it takes the list (or tuple) of items and unpacks it. By this it matches them to the arguments in the function. Of course, you could have a * both in the function definition and in the function call.
One place where the use of *args and **kwargs is quite useful is for subclassing.
class Foo(object):
def __init__(self, value1, value2):
# do something with the values
print value1, value2
class MyFoo(Foo):
def __init__(self, *args, **kwargs):
# do something else, don't care about the args
print 'myfoo'
super(MyFoo, self).__init__(*args, **kwargs)
This way you can extend the behaviour of the Foo class, without having to know too much about Foo. This can be quite convenient if you are programming to an API which might change. MyFoo just passes all arguments to the Foo class.
Here's an example that uses 3 different types of parameters.
def func(required_arg, *args, **kwargs):
# required_arg is a positional-only parameter.
print required_arg
# args is a tuple of positional arguments,
# because the parameter name has * prepended.
if args: # If args is not empty.
print args
# kwargs is a dictionary of keyword arguments,
# because the parameter name has ** prepended.
if kwargs: # If kwargs is not empty.
print kwargs
>>> func()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: func() takes at least 1 argument (0 given)
>>> func("required argument")
required argument
>>> func("required argument", 1, 2, '3')
required argument
(1, 2, '3')
>>> func("required argument", 1, 2, '3', keyword1=4, keyword2="foo")
required argument
(1, 2, '3')
{'keyword2': 'foo', 'keyword1': 4}
Here's one of my favorite places to use the ** syntax as in Dave Webb's final example:
mynum = 1000
mystr = 'Hello World!'
print("{mystr} New-style formatting is {mynum}x more fun!".format(**locals()))
I'm not sure if it's terribly fast when compared to just using the names themselves, but it's a lot easier to type!
One case where *args and **kwargs are useful is when writing wrapper functions (such as decorators) that need to be able accept arbitrary arguments to pass through to the function being wrapped. For example, a simple decorator that prints the arguments and return value of the function being wrapped:
def mydecorator( f ):
#functools.wraps( f )
def wrapper( *args, **kwargs ):
print "Calling f", args, kwargs
v = f( *args, **kwargs )
print "f returned", v
return v
return wrapper
*args and **kwargs are special-magic features of Python.
Think of a function that could have an unknown number of arguments. For example, for whatever reasons, you want to have function that sums an unknown number of numbers (and you don't want to use the built-in sum function). So you write this function:
def sumFunction(*args):
result = 0
for x in args:
result += x
return result
and use it like: sumFunction(3,4,6,3,6,8,9).
**kwargs has a diffrent function. With **kwargs you can give arbitrary keyword arguments to a function and you can access them as a dictonary.
def someFunction(**kwargs):
if 'text' in kwargs:
print kwargs['text']
Calling someFunction(text="foo") will print foo.
Just imagine you have a function but you don't want to restrict the number of parameter it takes.
Example:
>>> import operator
>>> def multiply(*args):
... return reduce(operator.mul, args)
Then you use this function like:
>>> multiply(1,2,3)
6
or
>>> numbers = [1,2,3]
>>> multiply(*numbers)
6
The names *args and **kwargs or **kw are purely by convention. It makes it easier for us to read each other's code
One place it is handy is when using the struct module
struct.unpack() returns a tuple whereas struct.pack() uses a variable number of arguments. When manipulating data it is convenient to be able to pass a tuple to struck.pack() eg.
tuple_of_data = struct.unpack(format_str, data)
# ... manipulate the data
new_data = struct.pack(format_str, *tuple_of_data)
without this ability you would be forced to write
new_data = struct.pack(format_str, tuple_of_data[0], tuple_of_data[1], tuple_of_data[2],...)
which also means the if the format_str changes and the size of the tuple changes, I'll have to go back and edit that really long line
Note that *args/**kwargs is part of function-calling syntax, and not really an operator. This has a particular side effect that I ran into, which is that you can't use *args expansion with the print statement, since print is not a function.
This seems reasonable:
def myprint(*args):
print *args
Unfortunately it doesn't compile (syntax error).
This compiles:
def myprint(*args):
print args
But prints the arguments as a tuple, which isn't what we want.
This is the solution I settled on:
def myprint(*args):
for arg in args:
print arg,
print
These parameters are typically used for proxy functions, so the proxy can pass any input parameter to the target function.
def foo(bar=2, baz=5):
print bar, baz
def proxy(x, *args, **kwargs): # reqire parameter x and accept any number of additional arguments
print x
foo(*args, **kwargs) # applies the "non-x" parameter to foo
proxy(23, 5, baz='foo') # calls foo with bar=5 and baz=foo
proxy(6)# calls foo with its default arguments
proxy(7, bar='asdas') # calls foo with bar='asdas' and leave baz default argument
But since these parameters hide the actual parameter names, it is better to avoid them.
You can have a look at python docs (docs.python.org in the FAQ), but more specifically for a good explanation the mysterious miss args and mister kwargs (courtesy of archive.org) (the original, dead link is here).
In a nutshell, both are used when optional parameters to a function or method are used.
As Dave says, *args is used when you don't know how many arguments may be passed, and **kwargs when you want to handle parameters specified by name and value as in:
myfunction(myarg=1)
I'm using the decorator module to decorate some functions. I want the decorator to be quite general, so I'm allowing it to have any number of arguments and keyword arguments (as long as there are more than two arguments):
from decorator import decorator
def wrap(f):
return decorator(_wrap, f)
def _wrap(function, t, f, *args, **kwargs):
print 't=', t
print 'f=', f
print 'args=', args
print 'kwargs=', kwargs
#wrap
def read(a, b, c=False, d=True):
pass
read(1, 2, d=True)
The issue is that the above return:
t= 1
f= 2
args= (False, True)
kwargs= {}
but the False and True come from c= and d=, so shouldn't they be in kwargs, i.e.:
t= 1
f= 2
args= (,)
kwargs= {'c':False, 'd':True}
?
c and d are positional arguments. Their names are included in the function object's metadata (because you use decorator, it's also preserved on the wrapper) and therefore you can refer to their names when calling the function, but they're still positional arguments and specifying them by their names merely leads to them being put into the correct positions in args. And it works as expected, so why is it an issue?
Just in case, check this other post talking about the same issue decorator python library hide the kwargs inside args (and giving the same answer as delnan)