I followed this to pass functions as arguments:
Passing functions with arguments to another function in Python?
However, I could not figure out how to pass function with its own arguments as names parameters
def retry(func, *args):
func(*args)
def action(args):
do something
retry(action, arg1, namedArg=arg2)
Here I get an exception:
TypeError: retry() got an unexpected keyword argument 'namedArg'
Normally, I can do:
action(arg1, namedArg=arg2)
Please help/
*args and it's sibling **kwargs are the names generally used for extra arguments and key word arguments. You are passing a kew word argument when you pass namedArg=arg2.
So, try this instead:
def retry(func, *args, **kwargs):
func(*args, **kwargs)
def action(*args, **kwargs):
do something
retry(action, arg1, namedArg=arg2)
If you instead use
def action(args, kwargs):
do something
Then you will end up with args as a list of arguments and kwargs as a dictionary of key word arguments, so in your case
args = [arg1]
kwargs = {'namedArg':arg2}
Read this, keyword arguments in python doc.
As the error clearly states that got an unexpected keyword argument 'namedArg'. where as you are providing only arguments in *args.
You will find plenty of examples to understand keyword arguments.
What you need is functools.
http://docs.python.org/2/library/functools.html#functools.partial
from functools import partial
def action(arg):
do something
def action2(arg=1):
do something
def action3(arg1, arg2=2):
do something
partial(action, arg1)
partial(action, arg1, arg2=3)
Related
When doing a method call in Python, in which cases do you use the = sign when entering arguments?
I noticed sometimes it's:
object.method(argument1 = ... , argument2 = ...)
and other times it's
object.method(... , ...)
Thanks in advance!
That types of arguments are called keyword arguments, probably you've seen that as (kwargs).
In a function you can pass 2 types of args, positional arguments and keyword-arguments.
def function(arg):
So you have to pass inside this function a positional argument, this means that you have to pass only the value for that arg like
function(1) or maybe a string function("hello") or maybe a list and so on; This type of arg is called position arg.
When you have to specify the name of the variable inside the brackets of a function call like function(name = "John"), you are using the keyword args.
If you want to understand more on this topic, i suggest you to see the unpack operator in Python (*) and then *args and **kwargs.
2 words to say what *args and **kwargs do in Python, they allows you to specify an unlimited number of arguments inside a function call.
def function(*args, **kwargs):
pass
function(1,2,3,"hello",[1,2,3],name="John",age=5)
How can we do function implementation for the following?
For optional and named arguments we write function in following way.
def funct(*args, **kwargs):
for arg in args:
print “arg =”, arg
for key in kwargs.keys():
print “arg[{0}]={1}”.format(key, kwargs[key])
If I want to call this function inside another function of same protocol, how can I implement?
def funct2(*args, **kwargs):
# call funct() above
funct(????????)
So is there any way to call the first funct() with optional arguments inside the new funct2() with the same type of optional arguments?
The syntax for calling a function is basically the same as when defining the function. So your funct2 would look like:
def funct2(*args, **kwargs):
# call funct() above
funct(*args, **kwargs)
Here are the Python docs covering the subject: https://docs.python.org/2/tutorial/controlflow.html#unpacking-argument-lists
Suppose I have a function get_data which takes some number of keyword arguments. Is there some way I can do this
def get_data(arg1, **kwargs):
print arg1, arg2, arg3, arg4
arg1 = 1
data['arg2'] = 2
data['arg3'] = 3
data['arg4'] = 4
get_data(arg1, **data)
So the idea is to avoid typing the argument names in both function calling and function definition. I call the function with a dictionary as argument and the keys of the dictionary become local variables of function and their values are the dictionary values
I tried the above and got error saying global name 'arg2' is not defined. I understand I can change the locals() in the definition of get_data to get the desired behavior.
So my code would look like this
def get_data(arg1, kwargs):
locals().update(kwargs)
print arg1, arg2, arg3, arg4
arg1 = 1
data['arg2'] = 2
data['arg3'] = 3
data['arg4'] = 4
get_data(arg1, data)
and it wouldn't work too. Also cant I achieve the behavior without using locals()?
**kwargs is a plain dictionary. Try this:
def get_data(arg1, **kwargs):
print arg1, kwargs['arg2'], kwargs['arg3'], kwargs['arg4']
Also, check documentation on keyword arguments.
If we examine your example:
def get_data(arg1, **kwargs):
print arg1, arg2, arg3, arg4
In your get_data functions's namespace, there is a variable named arg1, but there is no variable named arg2. so you can not reach a function or a variable that is not in your namespace.
In fact, in your namespace; there is a variable arg1 and a dictionary object called kwargs. using ** notation before the kwargs (name kwargs is not important in here, it can be something else too.) tells your python compiler that kwargs is a dictionary and all values in that dictionary will be evaluated as named parameters in your function definition.
Lets take a look at this example:
def myFunc(**kwargs):
do something
myFunc(key1='mykey', key2=2)
when you call myFunc with named parameters key1 and key2, your function definition acts like
def myFunc(key1=None, key2=None):
but with an exception! since myFunc have no named parameters, compiler do not know how to handle them directly since you can pass any named parameter to your function.
So your function accept those named parameters within a dictionary like you call your function:
myFunc({key1:'mykey', key2:2})
so, your function definition get those parameters within a dictionary. **kwargs defines your dictionary in that point, which also tell compiler that any named parameters will be accepted (by the help of ** signs before the kwargs)
def myFunc(**kwargs):
print kwargs
will print
{key1:'mykey', key2:2}
So in your example, you can use kwargs like a dictionary;
def myFunc(**kwargs):
kwargs['arg2']
kwargs.get('arg3')
I hope it is not complicated (:
I have a simple exception-logging decorator, which is handy for sending myself emails when my scripts throw exceptions.
def logExceptions(func):
def wrapper():
try:
func()
except Exception, e:
logger.exception(e)
return wrapper
However, if I want to decorate a class method, I have to modify wrapper() to take a 'self', otherwise I get the following error:
TypeError: wrapper() takes no arguments (1 given)
Of course, at that point I can't use it to decorate any non-class methods, because then this error occurs:
TypeError: wrapper() takes exactly 1 argument (0 given)
Is there a clean way to tackle this problem? Thank you =)
The usual thing is to define your wrapper so it accepts *args and **kwargs and passes them on to the function it wraps. This way it can wrap any function.
Also, I get the impression that what you are calling a "class method" is what Python calls an "instance method", and what you call "non-class method" is what Python calls a "function". A "non-class method" (e.g., instance method) in Python takes a self argument.
Difference between instance method, classmethod and staticmethod
First a note: both static method and class method are also functions, so standard function rules mostly apply to them. I understand your question is about the difference between static method (which has no extra arguments passed) and class method (which receives class in the first argument):
class Test(object):
def standard_method(*args, **kwargs):
# it is instance method (first argument will be instance)
return args, kwargs
#classmethod
def class_method(*args, **kwargs):
# it is class method (first argument will be class)
return args, kwargs
#staticmethod
def static_method(*args, **kwargs):
# it is static method (receives only arguments passed explicitly)
return args, kwargs
The proof (or rather self-explanatory example) is here:
>>> t = Test()
>>> t.standard_method()
((<__main__.Test object at 0x0000000002B47CC0>,), {})
>>> t.class_method()
((<class '__main__.Test'>,), {})
>>> t.static_method()
((), {})
As you see, the list of arguments passed differs depending on which type of method you choose. The problem you are facing is variable number of arguments.
Solution
There is a solution for that - use argument unpacking:
def some_decorator(func):
def wrapper(*args, **kwargs):
# do something here
# args is a tuple with positional args, kwargs is dict with keyword args
return func(*args, **kwargs)
return wrapper
After that, function returned by some_decorator will accept the same amount of arguments as decorated function.
So both these examples will work:
#some_decorator
def say_hello():
print 'hello'
#some_decorator
def say_something(something):
print something
Appendix
To give you fully complete example, it would be good if you would use such constructions (note usage of functools.wraps):
from functools import wraps
def some_decorator(func):
#wraps(func)
def wrapper(*args, **kwargs):
# do something here
# args is a tuple with positional args, kwargs is dict with keyword args
return func(*args, **kwargs)
return wrapper
The reason for that is listed in documentation for functools.wraps(): it preserves function name and docstring, effectively resulting in the wrapper looking like a wrapped function (which is useful sometimes).
An alternative to decorating is use sys.excepthook which is a callback that operates on all uncaught exceptions to which you can assign your custom logging function. The benefit is that then you dont need to mutilate (and more importantly, keep track of) every function that you are interested in logging exceptions for.
In python2.7, the argparse module has an add_argument method which can take a variable number of unnamed arguments before its keyword arguments as shown below:
parser = argparse.ArgumentParser(description='D')
parser.add_argument('-a', '-b', ... '-n', action='store', ... <other keyword args>)
As far as I know, function definitions as follow don't work:
def fxn(var_args*, action, otherstuff):
def fxn(action, otherstuff, var_args*): # results in conflict on action
What is the proper means to emulate the add_argument behaviour?
Python's argument definition order is...
Required and/or default-value arguments (if any)
variable-length positional arguments placeholder (*<name> if desired)
keyword arguments placeholder (**<name> if desired)
The positional arguments placeholder gets a list, the keyword arguments placeholder gets a dict.
add_arguments simply looks for keys in the dict of keyword arguments, rather than spelling out all of the possible arguments in the declaration. Something along the lines of...
def add_arguments(*posargs, **kwargs):
if 'action' in kwargs:
# do something
You can pass arbitrary number of arguments to a function.
Here is an example
def f(x, *args, **kwargs):
print x
for arg in args:
print arg
for key, value in kwargs:
print key + ': ' + value
Reading this will help: http://docs.python.org/tutorial/controlflow.html#keyword-arguments.