Python - passing a function as an argument to another function - python

I have two files;
The first file, myProgram.py, is a python file with a number of functions
one of the functions contained inside is myFunction
this function would be called with
import myProgram
myProgram.thisFunction()
myProgram.thatFunction()
The second file contains a menu system, with calls to the functions in myProgram.py
I'd like to call a particular function based on an argument passed to a function in file2
def file2_function(function):
myProgram.function
file2_function(thisFunction(x,y,z))
which would essentially create myProgram.thisfunction(x,y,z) and execute it.
I guess I could do this using a bunch of if/elif statements, say:
def file2_function(function):
if function == 1:
myProgram.thisFunction
elif function == 2:
myProgram.thatFunction
Though that could get messy as I'm already using a lot of if/elif/else statements for the menu system.
Is there a better way (or is the if/elif route the way to go?)

The *args in the function file2_function means the arguments to be passed to the function in which it calls:
def func1(a):
print a
def file2_function(function,*args):
function(*args)
file2_function(func1,4)
#4

You can create a dictionary where key is the name of the function, and value is the function itself. Short example:
functions = { 'add' : lambda x,y : x + y, 'mult': lambda x,y : x * y, 'div' : lambda x,y : x / y, 'sub' : lambda x,y : x - y }
functions['add'](1,2) # returns 3

#aga gave you a good hint. When I'm writing cli applications I usually do smth like:
def func1():
pass
def func2():
pass
def func3():
pass
def func_caller(name):
func_dict = {
'func1': func1,
'func2': func2,
'func3': func3
}
try:
func_dict[name]()
except KeyError:
print "no such func"

Alternatively you have getattr. See following snippet:
>>> import sys
>>> getattr(sys,'exc_info')
<built-in function exc_info>
>>> getattr(sys,'exc_info')()
(None, None, None)

Related

How can I call a lambda without defining it as a function?

For lambda functions in the following code,
def myfunc(n):
return lambda a : a * n
mydoubler = myfunc(2)
print(mydoubler(11))
I am trying to understand why mydoubler becomes <class 'function'> and how I can call mydoubler(11) without defining it as a function.
A lambda is a function, but with only one expression (line of code).
That expression is executed when the function is called, and the result is returned.
So the equivalent of this lambda:
double = lambda x: x * 2
is this def function:
def double(x):
return x * 2
You can read more here
A lambda is a function, so your code is doing something like
def myfunc(n):
def result(a):
return a * n
return result # returns a function
mydoubler = myfunc(2)
print(f(11))
You're asking how to call mydoubler without defining it as a function, which isn't the clearest question, but you can call it without naming it like so
print( myfunc(2)(11) )
Your myfunc is returning a lambda. Lambda is a small anonymous function. A lambda can take any number of arguments, but can only have one expression.
So after execution of the 3rd line, your mydoubler will become a lambda that's why when you try print(type(mydoubler)) it will return <class 'function'>.
Also in order to call mydoubler with 11, it must be function.
A lambda expression, like a def statement, defines functions. Your code could be equivalently written as
def myfunc(n):
def _(a):
return a * n
return _
mydoubler = myfunc(2)
print(mydoubler(11))
Because the inner function is simple enough to be defined as a single expression, using a lambda expression saves you the trouble of coming up with the otherwise unused name the def statement requires.
The key here is that the inner function closes over the value of n, so that the function returned by myfunc retains a reference to the value of the argument passed to myfunc. That is, mydoubler is hard-coded to multiply its argument by 2, rather than whatever value n may get later. (Indeed, the purpose of the closure is to create a new variable n used by the inner function, one which cannot easily be changed from outside myfunc.)
using decorator you can achive this
from functools import wraps
def decorator_func_with_args(arg1):
def decorator(f):
#wraps(f)
def wrapper(val):
result = f(val)
return result(arg1)
return wrapper
return decorator
#decorator_func_with_args(arg1=2)
def myfunc(n):
return lambda arg:arg*n
result = myfunc(1211)
print(result)
output
2422
Do you mean this?
mydoubler = lambda a : a * 2
mydoubler(11)

What is the best way in python to write docstrings for lambda functions?

I usually comment my functions using multi-line docstrings with """, as mentioned in :
https://www.python.org/dev/peps/pep-0257/
def func1(x):
"""
This function does ...
"""
...
But what is the best way to comment a lambda function ? I hesitate between :
# This function does ...
func2 = lambda x: ...
or :
func2 = lambda x: ...
""" This function does ... """
or else ?
tbh, even assigning a lambda to a variable seems unpythonic to me. if it needs a name, define it as a regular function. The difference between a lambda function and a regular function is that the latter has a __name__ attribute and an explicit return statement.
if you must add a docstring to a lambda, do it like this:
f = lambda x: x + 1
f.__doc__ = """adds 1 to input-arg"""
help(f)
# outputs the following:
help(f)
Help on function <lambda> in module __main__:
<lambda> lambda x
adds 1 to arg
This way, the documentation is actually available to the interpreter as a function docstring.
Quoting directly from pep-8
Always use a def statement instead of an assignment statement that binds a lambda expression directly to an identifier.
Yes:
def f(x): return 2*x
No:
f = lambda x: 2*x

Python 3: Checking if a function was called on by another function

In python 3, is there a way to check if another function executed a particular function? I want the computer to do something if a function was called by the itself and something else if another function called it. Here is an example:
def x():
y()
def y():
"""Psuedocode --->"""
if function y was called by function x:
print ("function y was called by another function")
elif function y was not called by function x:
print ("function y was called not called by another function")
Input ----> x()
Output ---> function y was called by another function
Input ---> y()
Output ---> function y was not called by another function
You can use the Python feature called "Inspect". It returns a list of frame records. The third element in each record is the caller name. Refer docs here: https://docs.python.org/3/library/inspect.html
import inspect
def x():
print inspect.stack()[1][3]
def y():
x()

Return function with function

I would like to do something like the following:
def getFunction(params):
f= lambda x:
do stuff with params and x
return f
I get invalid syntax on this. What is the Pythonic/correct way to do it?
This way I can call f(x) without having to call f(x,params) which is a little more messy IMO.
A lambda expression is a very limited way of creating a function, you can't have multiple lines/expressions (per the tutorial, "They are syntactically restricted to a single expression"). However, you can nest standard function definitions:
def getFunction(params):
def to_return(x):
# do stuff with params and x
return to_return
Functions are first-class objects in Python, so once defined you can pass to_return around exactly as you can with a function created using lambda, and either way they get access to the "closure" variables (see e.g. Why aren't python nested functions called closures?).
It looks like what you're actually trying to do is partial function application, for which functools provides a solution. For example, if you have a function multiply():
def multiply(a, b):
return a * b
... then you can create a double() function1 with one of the arguments pre-filled like this:
from functools import partial
double = partial(multiply, 2)
... which works as expected:
>>> double(7)
14
1 Technically a partial object, not a function, but it behaves in the same way.
You can't have a multiline lambda expression in Python, but you can return a lambda or a full function:
def get_function1(x):
f = lambda y: x + y
return f
def get_function2(x):
def f(y):
return x + y
return f

Function as an argument in a function

So here is the the problem
def func_1(x):
print 'function'
def func_2(x,y):
print 'function2'
def func_3():
n=func_1(x)
m=func_2(x,y)
i have 2 functions and i have a third one which needs to use the first 2 , the problem is that i don't know how to make it work . I give the arguments of the first two functions and it gives me an error , tried giving the functions as an argument , but it gives me a syntax error
i also tried of getting rid of the first function , solving the problem with a while cycle like this
counter = 0
while counter<10:
n=func_1(x)
m=func_2(x,y)
but it tells me that tuple object is not callable
If someone could tell me how to do it without defining the first 2 functions inside the third one i would be grateful
You are not passing func_3() any arguments, and still expecting it to know x and y
Also func_1 () and func_2 doen't return anything, so there is no need to do value = func() at func_3()
Try this:
def func_1(x):
print "i'm func1"
print x
def func_2(x,y):
print "i'm func2"
print x, y
def func_3(x, y):
func_1(x)
func_2(x, y)
func_3(1, 2)
It's hard to tell from your question, but it sounds like you are trying to get func3 to use functions passed as arguments? Something like
def func1(x):
return 2*x
def func2(x, y):
return 3*x + 2*y
def func3(x, y, fn1, fn2):
return fn1(x) + fn2(x, y)
def main():
print(5, 8, func1, func2)
if __name__=="__main__":
main()

Categories