Pass a function into another function as an argument, with some but not all of the arguments?
Passing functions with arguments to another function in Python? - Stack Overflow
How do I pass a method as a parameter in Python - Stack Overflow
Best way to pass arguments to a function that requires a large number of inputs?
Videos
Hello, I am new to python, and am trying to learn as I go for my machine learning class. In order to make some of my assignment work, I need to be able to pass a function in as an argument to another function, but have some of the arguments already filled out.
So for example, let’s say I wanted to pass the function “foo” to use in a function “bar”. Lets assume that foo takes the arguments a, b, and c. I could write
bar(foo)
but in order to call foo, I would need a, b and c in bar.
alternatively, I could write
bar(foo(a, b, c))
but this is going to pass in as a value, and I need all 3 values.
Let’s say I have a and b to pass in, but c is calculated within bar. Is there a way to do this so I can give bar a and b, but not c?
edit: I figured it out! He just wanted me to create a lambda function that passes the arguments into the function, and then pass that lambda as the argument.
Do you mean this?
def perform(fun, *args):
fun(*args)
def action1(args):
# something
def action2(args):
# something
perform(action1)
perform(action2, p)
perform(action3, p, r)
This is what lambda is for:
def perform(f):
f()
perform(lambda: action1())
perform(lambda: action2(p))
perform(lambda: action3(p, r))
Yes it is, just use the name of the method, as you have written. Methods and functions are objects in Python, just like anything else, and you can pass them around the way you do variables. In fact, you can think about a method (or function) as a variable whose value is the actual callable code object.
Since you asked about methods, I'm using methods in the following examples, but note that everything below applies identically to functions (except without the self parameter).
To call a passed method or function, you just use the name it's bound to in the same way you would use the method's (or function's) regular name:
def method1(self):
return 'hello world'
def method2(self, methodToRun):
result = methodToRun()
return result
obj.method2(obj.method1)
Note: I believe a __call__() method does exist, i.e. you could technically do methodToRun.__call__(), but you probably should never do so explicitly. __call__() is meant to be implemented, not to be invoked from your own code.
If you wanted method1 to be called with arguments, then things get a little bit more complicated. method2 has to be written with a bit of information about how to pass arguments to method1, and it needs to get values for those arguments from somewhere. For instance, if method1 is supposed to take one argument:
def method1(self, spam):
return 'hello ' + str(spam)
then you could write method2 to call it with one argument that gets passed in:
def method2(self, methodToRun, spam_value):
return methodToRun(spam_value)
or with an argument that it computes itself:
def method2(self, methodToRun):
spam_value = compute_some_value()
return methodToRun(spam_value)
You can expand this to other combinations of values passed in and values computed, like
def method1(self, spam, ham):
return 'hello ' + str(spam) + ' and ' + str(ham)
def method2(self, methodToRun, ham_value):
spam_value = compute_some_value()
return methodToRun(spam_value, ham_value)
or even with keyword arguments
def method2(self, methodToRun, ham_value):
spam_value = compute_some_value()
return methodToRun(spam_value, ham=ham_value)
If you don't know, when writing method2, what arguments methodToRun is going to take, you can also use argument unpacking to call it in a generic way:
def method1(self, spam, ham):
return 'hello ' + str(spam) + ' and ' + str(ham)
def method2(self, methodToRun, positional_arguments, keyword_arguments):
return methodToRun(*positional_arguments, **keyword_arguments)
obj.method2(obj.method1, ['spam'], {'ham': 'ham'})
In this case positional_arguments needs to be a list or tuple or similar, and keyword_arguments is a dict or similar. In method2 you can modify positional_arguments and keyword_arguments (e.g. to add or remove certain arguments or change the values) before you call method1.
Yes it is possible. Just call it:
class Foo(object):
def method1(self):
pass
def method2(self, method):
return method()
foo = Foo()
foo.method2(foo.method1)
For example, suppose I had a function which required 50 arguments and these arguments were stored in an object with 500 properties.
I could simply pass the object to the function, but then I’d be passing an addition 450 values that are not needed by the function. This feels like bad practice, but I’m not aware of whether or not that’s true.
EDIT: 50 args does indeed sound excessive (and I’ll admit that it’s a slight exaggeration). However, quite a lot of arguments are taken by this function because it is responsible for aggregating results from other models. In addition to taking in lots of inputs, there are also various aggregation settings that the user may specify.
The * and ** operators are used in two different situations.
When used as part of a function definition,
def save_name_for(self, *args, **kwargs):it is used to signify an arbitrary number of positional or keyword arguments, respectively. The point to remember is that inside the function
argswill be a tuple, andkwargswill be a dict.When used as part of a function call,
args = (1, 2) kwargs = {'last': 'Doe', 'first': 'John'} self.save_name_for(*args, **kwargs)the
*and**act as unpacking operators.argsmust be an iterable, andkwargsmust be dict-like. The items inargswill be unpacked and sent to the function as positional arguments, and the key/value pairs inkwargswill be sent to the function as keyword arguments. Thus,self.save_name_for(*args, **kwargs)is equivalent to
self.save_name_for(1, 2, last='Doe', first='John')
See also the saltycrane blog for an explanation with examples.
You pass them with syntax mirroring the argument syntax:
self.save_name_for(*args, **kwargs)
Note that you do not need to pass in self; save_name_for is already bound.
Command line arguments are passed as an array to the program, with the first being usually the program's location. So we skip argv[0] and move on to the other arguments.
This example doesn't include error checking.
from sys import argv
def operation(name, number):
...
contact_name = argv[1]
contact_no = argv[2]
operation(contact_name, contact_no)
Calling from command line:
python myscript.py John 5
You can use argparse to write user-friendly command-line interfaces.
import argparse
parser = argparse.ArgumentParser(description='You can add a description here')
parser.add_argument('-n', '--name', help='Your name', required=True)
args = parser.parse_args()
print args.name
To call the script use:
python script.py -n a_name