Functions as arguments to functions - python

I saw this example in a Python book, which showcases how to use a function as an argument to another function:
def diff2(f, x, h=1E-6):
r = (f(x-h) - 2*f(x) + f(x+h))/float(h*h)
return r
def g(t):
return t**(-6)
t = 1.2
d2g = diff2(g, t)
print d2g
My question is, how does this script work without providing an argument to function g? The line in question is:
d2g = diff2(g,t)
Shouldn't it be done like:
d2g = diff2(g(t), t)

g is passed as an argument to diff2. In diff2, that argument is called f, so inside diff2 the name f refers to the function g. When diff2 calls f(x-h) (and the other calls it does), it is calling g, and providing the argument.
In other words, when you do diff2(g, t), you are telling diff2 that g is the function to call. The arguments to g are provided in diff2:
f(x-h) # calls g with x-h as the argument
f(x) # calls g with x as the argument
f(x+h) # calls g with x+h as the argument
If you called diff2(g(t), t), you would be passing the result of g(1.2) as the argument. g would be called before calling diff2, and diff2 would then fail when it tries to call f, because f would be a number (the value g(1.2)) instead of a function.

The functions in question are rather random, and perhaps difficult to understand. Let's consider a simple example, a function sum which takes two numbers a and b, and returns their sum. Actually, we can easily define another function prod, which returns their product too.
def sum(a,b):
return a + b
def prod(a,b):
return a * b
Let's say we have another function compute, which takes as its arguments the operation (a function), and two operands (two numbers to call the function on). In compute, we call the given operation on the arguments.
def compute(fn, a, b):
return fn(a, b)
We can compute different things. We can compute the sum of two numbers:
compute(sum, 1, 3)
We can compute the product of two numbers:
compute(prod, 1, 3)
Basically, without parentheses after the function name, we're not actually calling the function, it's just another object in the namespace (which happens to be a function which we can call). We don't call the function until inside of compute, when we do fn(a,b).
Let's see what the console outputs look like:
>>> compute(sum,1,3)
4
>>> compute(prod,1,3)
3
>>> sum
<function sum at mem-address>
>>> prod
<function prod at mem-address>
>>> sum(1,2)
3

Related

Functions as a argument

Just started learning python and came across this
def f(g):
return g(2)
def square(x):
return x ** 2
print(f(square)) # which gives 4
How does inputting square into the f function equate to 4?
When you call a function, the value of the argument is assigned to the named parameter. The call
print(f(square))
can be thought of as "expanding" to
g = square
print(g(2))
Calling f(square) is square(2) which is 2**2 so 4
In python functions are first-class values, considered objects as anything else, hence you can pass them as parameters to another function.
In your case, you are "composing" f with g, which in turn has an invocation with fixed 2 inside f. In this sense, f is a function whose purpose is to feed 2 into another function, given as argument.
Knowing that g squares a number, it's easy to see how g(2) is 4, then f(g) will return 4.

Don't understand the inner function in python

I have this problem:
cons(a, b) constructs a pair, and car(pair) and cdr(pair) returns the first and last element of that pair. For example, car(cons(3, 4)) returns 3, and cdr(cons(3, 4)) returns 4.
Given this implementation of cons:
def cons(a, b):
def pair(f):
return f(a, b)
return pair
Implement car and cdr.
I don't get the function.
It has an inner function and calls an other function in the return. As far as I understood the inner functions is that these functions should depend on the functions above them. In this case on cons(..).
But the function is not using a or b. And why is the function f there? The task is to implement car and cdr, and function f should be given.
So could someone explain me this function? And how could I start with the task?
First of all: Python function objects are first class objects. A def statement results in a new function object, and you can retrieve that object by using the function name:
>>> def foo():
... return 'foo was called'
...
>>> foo
<function foo at 0x11b3d8ae8>
What this means is that you can assign that object to other names too, and you can pass them as parameters to function calls. You can then later on call the function object by adding (...) to the reference:
>>> bar = foo
>>> bar()
'foo was called'
The function name is assigned to in the current namespace. In a module, that's the globals, but in a function such as cons, the name is added as a local. return pair in the cons function then returns the function object pair to the caller.
And function parameters such as f and a and b are also variables; if you pass in a function object as a parameter, then parameter_name(...) will call paramater_name and pass in any arguments in the ... part. f(a, b) calls f and passes in a and b.
The next item to understand are closures; closures are an extra namespace attached to function objects, for variables from a surrounding scope.
In the following example, spam is a name in the closure of the bar function:
>>> def foo():
... spam = 'Vikings'
... def bar():
... return spam
... return bar
...
>>> foo()
<function foo.<locals>.bar at 0x11b44bf28>
>>> foo()()
'Vikings'
Calling foo() returns a new function object; the bar() function inside of foo(). Calling that returned function object produces 'Vikings', the value of the spam variable in the foo function. How did bar() get access to that? Via the closure:
>>> foo().__closure__
(<cell at 0x11b3c05b8: str object at 0x11b469180>,)
>>> foo().__closure__[0].cell_contents
'Vikings'
So nested functions can have access to names from the surrounding scope via closures. (Side note: it's not the value that's stored in a closure, it's the variable. The variable can change over time, and just like other variables accessing the name later will reflect the new value; if spam was changed later on, calling bar() again would return the new value).
Now to your function: cons() creates an inner function pair(), and pair() has access to the parameters a and b via its closure:
>>> def cons(a, b):
... def pair(f):
... return f(a, b)
... return pair
...
>>> cons(42, 81)
<function cons.<locals>.pair at 0x11b46f048>
>>> pair_42_81 = cons(42, 81)
>>> pair_42_81.__closure__
(<cell at 0x11b3c02b8: int object at 0x10f59a750>, <cell at 0x11b3c05b8: int object at 0x10f59ac30>)
>>> pair_42_81.__closure__[0].cell_contents
42
>>> pair_42_81.__closure__[1].cell_contents
81
The pair() function takes a parameter f, and calls that parameter, passing in a and b. Lets see what happens when we pass in print.
print is a function too, it is an object that you can call, and it writes the arguments to the console with spaces in between:
>>> print
<built-in function print>
>>> print('arg1', 'arg2')
arg1 arg2
If you passed that to the pair() function that cons() returns, you can see what f(a, b) does:
>>> pair_42_81(print)
42 81
print, passed to pair(), is assigned to f, and f(a, b) is exactly the same thing as print(a, b).
We can see that print() was called because the values are written out to the console. But you could also create a function that returns a new value. Say you have a function that adds up two numbers, and returns that value:
>>> def add(first, second):
... return first + second
...
>>> add(42, 81)
123
>>> pair_42_81(add)
123
We can call the function directly, and 123 is returned, or we can have pair_42_81() do it for us, and the same result is returned to us. Simple!
All this works because functions are objects and can be passed around like other variables, and because pair_42_81 has a = 42 and c = 81 stored in a closure, and will use those to call a given object f with those two arguments.
Next up are cdr() and car(), which will return either the first or last element of a pair. If cons(a, b) produces pair(f) returning f(a, b), then cdr() and car() must each create a function to pass to pair() that'll extract either a or b.
So create a nested function in each, and have cdr() and car() call pair() with that function. The nested function does the work of picking either a or b, and returns that value. Then return the result of the call to the outside world:
def car(pair):
def return_first(a, b):
return a
return pair(return_first)
def cdr(pair):
def return_last(a, b):
return b
return pair(return_last)
pair(return_first) calls return_first(a, b), a is returned, and car() can return that to the caller:
>>> car(cons(42, 81))
42
and the same applies to pair(return_last), only now b is returned:
>>> cdr(cons(42, 81))
81
You may be interested in the background of these operations; car, cdr and cons come from LISP, where cons a b Constructs a cell with two pointers (explaining the name), and car (meaning Contents of the Address part of the Register number in the IBM 704 instruction set LISP was created on) and cdr (meaning Contents of the Decrement part of the Register number in 704 language) take the first and remainder parts of such a cell. See this Wikipedia article on the names.
This is called a closure. Two basic elements
the pair function knows the values of a and b. They are just like local variables in that respect
the cons function returns a function, not a value. You have to call the result again
So, when you call cons(a, b) you get a function that does something to a and b, only it doesn't know what yet. You have to pass another function for that. Eg
my_f = cons(1, 2)
result = my_f(lambda x, y: x + y)
print(result) # 3
How this is related to your assignment is not very clear. I would only assume that for car, you only want the element a (the head), and for cdr you want the element b (the rest of the list). So, the functions would just return the one argument and ignore the other. Eg
car_f = lambda x, y: x
cdr_f = lambda x, y: y
cons is a function which takes two arguments, a and b and returns a function pair.
The function pair takes a function f as an argument which consumes two arguments.
def cons(a, b):
def pair(f):
return f(a, b)
return pair
f = lambda n, m: n**2 + m**3
car = lambda n, m: n
cdr = lambda n, m: m
print(cons(2, 3)(f))
print(cons(2, 3)(car))
print(cons(2, 3)(cdr))
f returns 31 = 2**2 + 3**3
Note how cons has two times the parenthesis (...) - once, for its own call and another time for the returned functions call.
Please note this answer to be able to call car(cons(2, 3)). You might also be interested in Why would a program use a closure?
I manually converted cons function the Javascript version and then implemented the quiz:
cons(a, b) constructs a pair, and car(pair) and cdr(pair) returns the first and last element of that pair. For example, car(cons(3, 4)) returns 3, and cdr(cons(3, 4)) returns 4.Given this implementation of cons:
def cons(a, b):
def pair(f):
return f(a, b)
return pair
Implement car and cdr.
Here is the solution
function cons(a, b) {
function pair(f) {
return f(a, b);
}
return pair;
}
function car(pair) {
return pair((a, b) => a);
};
function cdr(pair) {
return pair((a, b) => b);
};
console.log(car(cons(3,4)));
console.log(cdr(cons(3,4)));
Use lambda expressions
def cons(a, b):
def pair(f):
return f(a, b)
return pair
def car(pair):
return pair(lambda a, b: a)
def cdr(pair):
return pair(lambda a, b: b)

Python functions with multiple parameter brackets

I've been having trouble understanding what h(a)(b) means. I'd never seen one of those before yesterday, and I couldn't declare a function this way:
def f (a)(b):
return a(b)
When I tried to do def f (a, b):, it didn't work either. What do these functions do? How can I declare them? And, finally, what's the difference between f(a, b)and f(a)(b)?
Functions with multiple parameter brackets don't exist, as you saw when you tried to define one. There are, however, functions which return (other) functions:
def func(a):
def func2(b):
return a + b
return func2
Now when you call func() it returns the inner func2 function:
>>> func2 = func(1) # You don't have to call it func2 here
>>> func2(2)
3
But if you don't need the inner function later on, then there's no need to save it into a variable and you can just call them one after the other:
>>> func(1)(2) # func(1) returns func2 which is then called with (2)
3
This is a very common idiom when defining decorators that take arguments.
Notice that calling func() always creates a new inner function, even though they're all named func2 inside of the definition of our func:
>>> f1 = func(1)
>>> f2 = func(1)
>>> f1(1), f2(1)
(2, 2)
>>> f1 is f2
False
And, finally, what's the difference between f(a, b)and f(a)(b)?
It should be clear now that you know what f(a)(b) does, but to summarize:
f(a, b) calls f with two parameters a and b
f(a)(b) calls f with one parameter a, which then returns another function, which is then called with one parameter b
f(a)(b) just means that the expression f(a) returns a value that is itself callable. It's a short form of
g = f(a)
g(b)
You might be more comfortable adding a pair of redundant parentheses to emphasize that this is not a single syntactic construct.
(f(a))(b) # f(a) is evaluated first, then the result is applied to b
It is exactly analogous to the same doubling of square brackets for indexing nested dictionaries.
d1[x][y]
is equivalent to
d2 = d1[x]
d2[y]
Lets say we have an expression like
f(a)(b)
then, f(a) returns a function itself which gets invoked with argument b. Consider the following example
def f(a):
def g(b):
return a * b
return g
Then f(5)(4) evaluates to 5 * 4, since f(5) returns a function which is basically
def g(b):
return 5 * b
One could now do stuff like this
mult_by_5 = f(5)
[mult_by_5(x) for x in range(10)]
Let's be fancy, what about more nested functions?:
def f(a):
def g(b):
def h(c):
return a * b *c
return h
return g
f(2)(3)(4) # 24

Passing a function as an argument vs Calling it inside. Which one is recomended in Python

Lets say I have three functions in one module as defined below:
def add_nums(a, b):
return a + b
def sum_and_square_one(add_nums, a, b):
result = add_nums(a,b)
return result*result
def sum_and_square_two(a, b):
result = add_nums(a,b)
return result*result
Both functions sum_and_square_one and sum_and_square_two do the same task. But the former takes add_nums as an argument while the latter calls add_nums inside. My question is which one is the better way. Passing a function as an argument or calling inside a function?
If you always want to call the same function then there is no point in passing it as an argument every time. (this is the case in your example)
If you, however, want to dynamically call different (maybe similar) functions, then passing the appropiate function as an argument would make sense.
Depends on your use case. Do you need the function to change the way it works depending on that argument?
Or, rewriting your meaningless example into a bit less meaningless example (but still quite):
def add_nums(a, b):
return a + b
def do_something_then_square(a, b, what_to_do):
result = what_to_do(a, b)
return result * result
def sum_then_square(a, b):
result = add_nums(a, b)
return result * result
# Then you do:
sum_then_square(2, 5) # 49
do_something_then_square(2, 5, what_to_do=add_nums) # 49
do_something_then_square(2, 5, what_to_do=lambda a, b: a + b) # 49
do_something_then_square(2, 5, what_to_do=lambda a, b: a * b) # 100
do_something_then_square(2, 5, what_to_do=min) # 4
do_something_then_square(2, 5, what_to_do=complex) # (-21+20j)
Only question is: do you need that added flexibility? Otherwise it's just useless additional typing. That question must be answered on a case by case basis; it needs a complete example to give a useful answer.

How to define a function that output another function?

I want to define a function that takes some arguments as input, and uses them to make another function, then outputs the new function.
For example:
makeIncrease(n) --> return a function that takes an argument, and return (argument + n)
applyIncrease(increaseFn, m) --> will apply increaseFn to argument m
So if I do this: applyIncrease(makeIncrease(n), m) --> will return m+n
How can I do it in python?
You can read about decorators in Python for more on this. For your specific question:
def applyIncrease(increaseFn, m):
return increaseFn(m)
def makeIncrease(n):
def _innerFn(arg):
return arg + n
return _innerFn
applyIncrease accepts a function and argument, and applies the function to the argument.
makeIncrease accepts an argument n.
Let's say n=2 for the sake of an example. makeIncrease(2) returns a function that takes an argument and adds 2 to it.
Although I began _innerFn with an underscore, this is only a convention - the underscore is not required for the decorator to work.
Note also that functions are first class objects in Python, and that makeIncrease returns _innerFn and not _innerFn(). Return functions exactly as you would variables or object references - no parentheses.
Here are your functions in the interpreter. Note that the object reference wrapped_function refers to _innerFn, i.e. the return value of makeIncrease(2)
>>> wrapped_function = makeIncrease(2)
>>> wrapped_function
<function _innerFn at 0x100496758>
>>> total = applyIncrease(wrapped_function, 3)
>>> total
5
class Example:
def result():
def nestedResult(a,b):
multiply = a*b
return multiply
return nestedResult
if __name__ == "__main__":
x = result()
print "multiplication_result:", x(1,10)

Categories

Resources