Function binding in python - python

n = 7
def f(x):
n = 8
return x + 1
def g(x):
n = 9
def h():
return x + 1
return h
def f(f, x):
return f(x + n)
f = f(g, n)
g = (lambda y: y())(f)
I'm trying to understand and keep track of all the changes in the binding of functions, but cannot seem to grasp why the y parameter in the lambda function gets binded to h() on being called.
The transition from step 14-15 in this Python Tutor link to be precise

Let's change the names of the functions so that twisted code is easier to follow. We can name then sequentially like fun_n and reassign the names after each function definition. I added some comments too
The first one would be
n = 7
def fun_1(x):
n = 8
return x + 1
f = fun1
The second one:
def fun_2(x):
n = 9
def h():
return x + 1
return h
g = fun_2
Now we are ready for some bad renaming
def fun_3(f, x):
return f(x + n)
f = fun_3
And now...
f = f(g, n)
which is equivalent to fun_3(fun2, n) with n=7.
fun_3 will return fun_2(7+n), again with n=7.
fun_2 will return a closure of h with x=14, so it will return a function that returns the result of 14 + 1. So f is now a function that always return 15
Finally,
g = (lambda y: y())(f)
creates a lambda function that calls whatever parameter is passed to it, and calls it passing f as a parameter. It is equivalent to:
fun_4 = lambda y: y()
g = fun_4(f)
I don't think it is really useful as an excercise.

Related

Python Second Level Parameter not Passing into Third Level

I am completing a project for school and am wondering what I did wrong in this code.
In Python, parameters passed through more nested functions should be able to be referenced, but the n parameter is not able to be compared to 0 in myFunc2, the error "local variable referenced before assignment." The doctests included show that, for example, it should run cycle(f1, f2, f3) with add1, times2, and add3 (which work just fine), run myFunc(n) with 0 passed as n, and myFunc2(x) with 5 passed as x. (Also works fine) I'm just curious why the n parameter doesn't seem to be coming through?
I was able to find a work around where I just make a global variable and use it in place of n and that solved the issue, but my goal is to understand where I went wrong.
def cycle(f1, f2, f3):
def myFunc(n):
def myFunc2(x):
while n > 0:
if n > 0:
x = f1(x)
n -= 1
if n > 0:
x = f2(x)
n -= 1
if n > 0:
x = f3(x)
n -= 1
return x
return myFunc2
return myFunc
>>> def add1(x):
... return x + 1
>>> def times2(x):
... return x * 2
>>> def add3(x):
... return x + 3
>>> my_cycle = cycle(add1, times2, add3)
>>> identity = my_cycle(0)
>>> identity(5)
5
>>> add_one_then_double = my_cycle(2)
>>> add_one_then_double(1)
4
>>> do_all_functions = my_cycle(3)
>>> do_all_functions(2)
9
>>> do_more_than_a_cycle = my_cycle(4)
>>> do_more_than_a_cycle(2)
10
>>> do_two_cycles = my_cycle(6)
>>> do_two_cycles(1)
19

Function call loops [duplicate]

This question already has answers here:
Why does my recursive function return None?
(4 answers)
Closed 2 years ago.
I seem not to be able to understand something fundamental. I have a function A which calls function B and proceeds with the results from it. Function B on the other hand does some iterative calculations and gets called by other functions repeatedly until the iteration is satisfied. When the iteration is satisfied, what I want is one result for function A (from function B), but I seem to get as many results as function B is iteratively called and my code just begins to act silly. It generally gives None result.
Here is what I mean script-wise:
def func_A():
x = 1
y = 1
result_A = func_B(x, y)
print(result_A)
def func_B(x, y):
result_B = x + y
if result_B < 10:
func_C(x,y)
else:
return result_B
def func_C(x, y):
x = x + 1
y = y + 1
func_B(x,y)
func_A()
What I want is func_A call to print 16 when x and y reach 4, however it returns None. I have some complicated nest of functions so I need to solve this problem with this function structure. If anyone could help I would appreciate it very much.
Please see following code.
I added return when call func_C and func_B.
def func_A():
x = 1
y = 1
result_A = func_B(x, y)
print(result_A)
def func_B(x, y):
result_B = x + y
if result_B < 10:
return func_C(x, y)
return result_B
def func_C(x, y):
x = x + 1
y = y + 1
return func_B(x, y)
func_A()
I agree with #Super Star but..
def func_B(x, y):
result_B = x * y #if you want 16 as an answer modify + to *

Calculating derivative of trinomial using the function as a parameter

I need to calculate the derivative of a trinomial function in another function using the former as a parameter. This is my code so far:
def derivative(func):
num=func(a,b,c)
third=func(0,0,c)
first=func(a,0,0)
return (num-third)/x+first/x
def make_quadratic(a, b, c):
return lambda x: x*x*a+b*x+c
I suppose that by using the make_quadratic function I had to add 3 parameters (a,b,c) in func as well. What I am trying to do is remove c, divide with x and then add ax so that the resulting derivative is 2ax+b, I cannot however run the code since for some reason a,b,c are not defined even though I do give them values when I call the function.
Write yourself a class like the following one:
class TrigonomialFunction:
def __init__(self, a, b, c):
self.a, self.b, self.c = a, b, c
def calculate(self, x):
return self.a * x ** 2 + self.b * x + self.c
def derivate(self):
return TrigonomialFunction(0, 2 ** self.a, self.b)
def __str__(self):
return "f(x) = %s x**2 + %s * x + %s" % (self.a, self.b, self.c)
Which can then get used in the following way:
f = TrigonomialFunction(2, 3, -5)
print(f) # will return f(x) = 2 x**2 + 3 * x + -5
print(f.calculate(1)) # returns 0
print(f.calculate(-1)) # returns -6
derivateOfF = f.derivate()
print(derivateOfF) # returns f(x) = 0 x**2 + 4 * x + 3 which can be simplified to f(x) = 4*x + 3
print(derivateOfF.calculate(0)) # returns 3
derivateOfderivateOfF = derivateOfF.derivate()
print(derivateOfderivateOfF) # guess ;)
You can calculate the derivative of any function using sympy.
For your function, you can use:
import sympy
def get_derivative(func, x):
return sympy.diff(func, x)
def make_quadratic(a, b, c):
x = sympy.symbols('x')
func = a * x**2 + b * x + c
return func, x
func, x = make_quadratic(1, 2, 3)
print(get_derivative(func, x))
Which returns 2*x + 2

How to do numerical integration in python?

I can't install anything new I need to use the default python library and I have to integrate a function. I can get the value for any f(x) and I need to integrate from 0 to 6 for my function f(x).
In discrete form, integration is just summation, i.e.
where n is the number of samples. If we let b-a/n be dx (the 'width' of our sample) then we can write this in python as such:
def integrate(f, a, b, dx=0.1):
i = a
s = 0
while i <= b:
s += f(i)*dx
i += dx
return s
Note that we make use of higher-order functions here. Specifically, f is a function that is passed to integrate. a, b are our bounds and dx is 1/10 by default. This allows us to apply our new integration function to any function we wish, like so:
# the linear function, y = x
def linear(x):
return x
integrate(linear, 1, 6) // output: 17.85
# or using lamdba function we can write it directly in the argument
# here is the quadratic function, y=x^2
integrate(lambda x: x**2, 0, 10) // output: 338.35
You can use quadpy (out of my zoo of packages):
import numpy
import quadpy
def f(x):
return numpy.sin(x) - x
val, err = quadpy.quad(f, 0.0, 6.0)
print(val)
-17.96017028290743
def func():
print "F(x) = 2x + 3"
x = int(raw_input('Enter an integer value for x: '))
Fx = 2 * x + 3
return Fx
print func()
using the input function in python, you can randomly enter any number you want and get the function or if hard coding this this necessary you can use a for loop and append the numbers to a list for example
def func2():
print "F(x) = 2x + 3"
x = []
for numbers in range(1,7):
x.append(numbers)
upd = 0
for i in x:
Fx = 2 * x[upd] + 3
upd +=1
print Fx
print func2()
EDIT: if you would like the numbers to start counting from 0 set the first value in range to 0 instead of 1

return multiple values from scipy root finding / optimization function

I'm trying to return multiple values that are obtained inside a scipy root finding function (scipy.optimize.root).
For example:
B = 1
def testfun(x, B):
B = x + 7
return B**2 + 9/18 - x
y = scipy.optimize.root(testfun, 7, (B))
Is there any way to return the value of B without using globals?
I'm not aware of anything SciPy specific, but how about a simple closure:
from scipy import optimize
def testfun_factory():
params = {}
def testfun(x, B):
params['B'] = x + 7
return params['B']**2 + 9/18 - x
return params, testfun
params, testfun = testfun_factory()
y = optimize.root(testfun, 7, 1)
print(params['B'])
Alternatively, an instance of a class with __call__ could also be passed as the callable.

Categories