Which object does name "g" bind to? - python

The below assignment is taken from here:
Q5. Define the repeated function from Homework 2 by calling reduce with compose1 as the first argument. Add only a single expression to the starter implementation below:
def square(x):
return x*x
def compose1(f, g):
"""Return a function of x that computes f(g(x))."""
return lambda x: f(g(x))
from functools import reduce
def repeated(f, n):
"""Return the function that computes the nth application of f, for n>=1.
f -- a function that takes one argument
n -- a positive integer
>>> repeated(square, 2)(5)
625
>>> repeated(square, 4)(5)
152587890625
"""
assert type(n) == int and n > 0, "Bad n"
return reduce(compose1, "*** YOUR CODE HERE ***" )
To complete this assignment, I would like to understand, to what does g bind to? f binds to the square function.

First, what should repeated(f, 4) return?
A function that, when called on some arbitrary arg, will return f(f(f(f(arg)))).
So, if you want to build that with compose1, you'll need to return either compose1(compose1(compose1(f, f), f), f) or compose1(f, compose1(f, compose1(f, f))).
Now, look at what reduce does, and figure out what it's going to pass to compose1 each time. Clearly your iterable argument has to either start or end with f itself. But what else do you want there to make sure you get one of the two acceptable results?
And meanwhile, inside each call to compose1 except the last, one of the two arguments has to be the repeated function's f, while the other will be the result of another call to compose1. (The last time, of course, they'll both be f.) Figure out which of those is f and which is g, and how you get reduce to pass the right values for each, and you've solved the problem.

Related

Double numbers in Python using Lambda

I am trying to double numbers using Lambda function in python but can't understand the function that's all because I'm starting to learn python. Below is the function:
def myfunc(n):
return lambda a : a * n
mydoubler = myfunc(2)
print(mydoubler(11))
I just need to understand how this code is working. Any help will be much appreciated.
def myfunc(n): # this function is taking input n and returning a function object
return lambda a : a * n # this function is taking input as a and we are returning this function object
mydoubler = myfunc(2) # now we are calling the returned function object if you print(mydoubler)-> this will give you function object
print(mydoubler(11)) # here we are calling the lambda function with parameters
If you want to implement it without lambda then you can use partial
from functools import partial
def double(n, a):
return a * n
def my_func1(n):
return partial(double,n)
mydoubler = my_func1(2)
print(mydoubler(11))
Your myfunc function creates and returns a closure. In this case, it returns a function that returns its argument times n. The tricky part is that n refers to the value in the specific call frame for myfunc. In your example, n has the value 2. That instance of n is specific to that particular call to myfunc. So if you called myfunc several times in a row, with several different values for n, each of the returned lambda functions would refer to a unique value of n unrelated to the other values.
Note that the use of lambda is optional. It's just shorthand for an anonymous function. For example, you could have written myfunc as:
def myfunc(n):
def f(a):
return a * n
return f
which would produce the same result.
Back to the original question, here's an example of multiple closures coexisting:
def myfunc(n):
def f(a):
return a * n
return f
mydoubler = myfunc(2)
mytripler = myfunc(3)
print(mydoubler(11))
print(mytripler(11))
This prints 22 followed by 33. This works because mydoubler and mytripler each refer to different instances of n.
The value of n can even be modified by calls to the returned closure. For example:
def myfunc(n):
def f(a):
nonlocal n
n += a
return n
return f
func = myfunc(100)
print(func(1))
print(func(5))
This prints 101 followed by 106. In this example, the nonlocal declaration is needed since f assigns to n. Without it, n would be taken to be local to f.

Intermediate results from recursion

I have a problem where I need to produce something which is naturally computed recursively, but where I also need to be able to interrogate the intermediate steps in the recursion if needed.
I know I can do this by passing and mutating a list or similar structure. However, this looks ugly to me and I'm sure there must be a neater way, e.g. using generators. What I would ideally love to be able to do is something like:
intermediate_results = [f(x) for x in range(T)]
final_result = intermediate_results[T-1]
in an efficient way. While my solution is not performance critical, I can't justify the massive amount of redundant effort in that first line. It looks to me like a generator would be perfect for this except for the fact that f is fundamentally much more suited to recursion in my case (which at least in my mind is the complete opposite of a generator, but maybe I'm just not thinking far enough outside of the box).
Is there a neat Pythonic way of doing something like this that I just don't know about, or do I just need to just capitulate and pollute my function f by passing it an intermediate_results list which I then mutate as a side-effect?
I have a generic solution for you using a decorator. We create a Memoize class which stores the results of previous times the function is executed (including in recursive calls). If the arguments given have already been seen, the cached versions are used to quickly lookup the result.
The custom class has the benefit over an lru_cache in that you can see the results.
from functools import wraps
class Memoize:
def __init__(self):
self.store = {}
def save(self, fun):
#wraps(fun)
def wrapper(*args):
if args not in self.store:
self.store[args] = fun(*args)
return self.store[args]
return wrapper
m = Memoize()
#m.save
def fibo(n):
if n <= 0: return 0
elif n == 1: return 1
else: return fibo(n-1) + fibo(n-2)
Then after running different things you can see what the cache contains. When you run future function calls, m.store will be used as a lookup so calculation doesn't need to be redone.
>>> f(8)
21
>>> m.store
{(1,): 1,
(0,): 0,
(2,): 1,
(3,): 2,
(4,): 3,
(5,): 5,
(6,): 8,
(7,): 13,
(8,): 21}
You could modify the save function to use the name of the function and the args as the key, so that multiple function results can be stored in the same Memoize class.
You can use your existing solution that makes many "redundant" calls to f, but employ the use of function caching to save the results to previous calls to f.
In other words, when f(x1) is called, it's input arguments and corresponding return values are saved, and the next time it is called, the result is simply pulled from the cache
see functools.lru_cache for the standard library solution to this
ie:
from functools import lru_cache
#lru_cache
intermediate_results = [f(x) for x in range(T)]
final_result = intermediate_results[T-1]
Note, however, f must be a pure function (no side-effects, 1-to-1 mapping) for this to work properly
Having considered your comments, I'll now try to give another perspective on the problem.
So, let's consider a concrete example:
def f(x):
a = 2
return g(x) + a if x != 0 else 0
def g(x):
b = 1
return h(x) - b
def h(x):
c = 1/2
return f(x-1)*(1+c)
I
First of all, it should be mentioned that (in our particular case) the algorithm has form of: f(x) = p(f(x - 1)) for some p. It follows that f(x) = p^x(f(0)) = p^x(0). That means we should just apply p to 0 x times to get the desired result, which can be done in an iterative process, so this can be written without recursion. Though I believe that your real case is much harder. Moreover, it would be too boring and uninformative to stop here)
II
Generally speaking, we can divide all possible solutions into two groups: the ones that require refactoring (i.e. rewriting functions f, g, h) and the ones that do not. I have little to offer from the latter one (and I don't think anyone can). Consider the following, however:
def fk(x, k):
a = 2
return k(gk(x, k) + a if x != 0 else 0)
def gk(x, k):
b = 1
return k(hk(x, k) - b)
def hk(x, k):
c = 1/2
return k(fk(x-1, k)*(1+c))
def printret(x):
print(x)
return x
f(4, printret) # see what happens
Inspired by continuation-passing style, but that's totally not it.
What's the point? It's something between your idea of passing a list to write down all the computations and memoizing. This k carries additional behavior with it, such as printing or writing to list (you can make a function that writes to some list, why not?). But if you look carefully you'll see that it lefts inner code of these functions practically untouched (only input and output to function are affected), so one can produce a decorator associated with a function like printret that does essentially the same thing for f, g, h.
Pros: no need to modify code, much more flexible than passing a list, no additional work (like in memoizing).
Cons: Impure (printing or modifying sth), not so flexible as we would like.
III
Now let's see how modifying function bodies can help. Don't be afraid of what's written below, take your time and play with that thing a little.
class Logger:
def __init__(self, lst, cur_val):
self.lst = lst
self.cur_val = cur_val
def bind(self, f):
res = f(self.cur_val)
return Logger([self.cur_val] + res.lst + self.lst, res.cur_val)
def __repr__(self):
return "Logger( " + repr({'value' : self.cur_val,'lst' : self.lst}) + " )"
def unit(x):
return Logger([], x)
# you can also play with lala
def lala(x):
if x <= 0:
return unit(1)
else:
return lala(x - 1).bind(lambda y: unit(2*y))
def f(x):
a = 2
if x == 0:
return unit(0)
else:
return g(x).bind(lambda y: unit(y + a))
def g(x):
b = 1
return h(x).bind(lambda y: unit(y - b))
def h(x):
c = 1/2
return f(x-1).bind(lambda y: unit(y*(1+c)))
f(4) # see for yourself
Logger is called a monad. I'm not very familiar with this concept myself, but I guess I'm doing everything right) f, g, h are functions that take a number and return a Logger instance. Logger's bind takes in a function (like f) and returns Logger with new value (computed by f) and updated 'logs'. The key point - as I see it - is the ability to do whatever we want with collected functions in the order the resulting value was calculated.
Afterword
I'm not at all some kind of 'guru' of functional programming, I believe I'm missing a lot of things here. But what I've understood is that functional programming is about inversing the flow of the program. That's why, for instance, I totally agree with your opinion about generators being opposed to functional programming. When we use generator gen in, say, function func, we yield values one by one to func and func does sth with them in e.g. a loop. The functional approach would be to make gen a function taking func as a parameter and make func perform computations on 'yielded' values. It's like gen and func exchanged their places. So the flow is inversed! And there are plenty of other ways of inversing the flow. Monads are one of them.
itertools islice gets a generator, start value and stop value. it will give you the elements between the start value and stop value as a generator. if islice is not clear you can check the docs here https://docs.python.org/3/library/itertools.html
intermediate_result = map(f, range(T))
final_result = next(itertools.islice(intermediate_result, start=T-1, stop=T))

python calling function twice one after another but second storing value from first

I am using python so can someone tell me how to call same function twice in python but when you call it the second time it should be changed an already have value stored in it when you called the function the first time, so I basically mean you are calling the function first time and right after that you are calling it again but with the return value from the first time you called that function.
Assuming you have a function that has both a parameter and a return value:
def myFunction(input):
# do something with input
return input
To have a second instance of the function use the result of the first instance, you can simply nest the functions:
result = myFunction(myFunction(value))
you can create function that will apply n-times
def multf(f, n, x):
if n == 0:
return x
return multf(f, n-1, f(x))
so here we apply lambda sqr 3 times, it becomes f(f(f(x)))
sqr = lambda x: x**2
print(multf(sqr,3,2))
256

Python Lambda usage

Im trying to learn how to utilize the lambda function and i am having some difficulties.
example from HomeWork.
i have the following functions
def square(x):
return x**2
def incr(x):
return x+1
i need to create a function called 'repeated' that will take one of the above functions + an integer and will return some value that depends on the times the functions have been called IE:
repeated (incr,4)(2)
6
repeated (square,2)(5)
625
using a 'compose' function.
def compose(f,g):
return lambda x:f(g(x))
thank in advance for an explanation.
If you should use a lambda, you can use recursion like this:
def repeated(func, times):
return lambda x: repeated(func, times - 1)(func(x)) if times > 0 else x
what repeated return is a function waiting for an argument, x,and then it activates itself times times (descriptive...) on x
When it should no longer activate itself (in other words, times <= 0, it stops and returns the x the last call received.
You can use compose in the same manner as follows:
If you want to use compose you can do this:
def repeated(func, times):
return compose(func, repeated(func, times-1)) if times > 0 else lambda x
What this does is just call compose recursively times - 1 more times, using repeated, until no more composing is needed.
Edit:
Python's standard implementation and recursion don't get along too well, both of these solution are correct, but using a loop is more pythonic. Another answer is available that does just that.
repeated needs to return a callable too; compose() can produce that callable for you, but you need to apply it multiple times:
def repeated(f, count):
callable = f
for _ in range(count - 1):
callable = compose(f, callable)
return callable
So if count is 1, the original f() is returned. For count = 2, f(f()) is returned, etc.

calculating current value based on previous value

i would like to perform a calculation using python, where the current value (i) of the equation is based on the previous value of the equation (i-1), which is really easy to do in a spreadsheet but i would rather learn to code it
i have noticed that there is loads of information on finding the previous value from a list, but i don't have a list i need to create it! my equation is shown below.
h=(2*b)-h[i-1]
can anyone give me tell me a method to do this ?
i tried this sort of thing, but that will not work as when i try to do the equation i'm calling a value i haven't created yet, if i set h=0 then i get an error that i am out of index range
i = 1
for i in range(1, len(b)):
h=[]
h=(2*b)-h[i-1]
x+=1
h = [b[0]]
for val in b[1:]:
h.append(2 * val - h[-1]) # As you add to h, you keep up with its tail
for large b list (brr, one-letter identifier), to avoid creating large slice
from itertools import islice # For big list it will keep code less wasteful
for val in islice(b, 1, None):
....
As pointed out by #pad, you simply need to handle the base case of receiving the first sample.
However, your equation makes no use of i other than to retrieve the previous result. It's looking more like a running filter than something which needs to maintain a list of past values (with an array which might never stop growing).
If that is the case, and you only ever want the most recent value,then you might want to go with a generator instead.
def gen():
def eqn(b):
eqn.h = 2*b - eqn.h
return eqn.h
eqn.h = 0
return eqn
And then use thus
>>> f = gen()
>>> f(2)
4
>>> f(3)
2
>>> f(2)
0
>>>
The same effect could be acheived with a true generator using yield and send.
First of, do you need all the intermediate values? That is, do you want a list h from 0 to i? Or do you just want h[i]?
If you just need the i-th value you could us recursion:
def get_h(i):
if i>0:
return (2*b) - get_h(i-1)
else:
return h_0
But be aware that this will not work for large i, as it will exceed the maximum recursion depth. (Thanks for pointing this out kdopen) In that case a simple for-loop or a generator is better.
Even better is to use a (mathematically) closed form of the equation (for your example that is possible, it might not be in other cases):
def get_h(i):
if i%2 == 0:
return h_0
else:
return (2*b)-h_0
In both cases h_0 is the initial value that you start out with.
h = []
for i in range(len(b)):
if i>0:
h.append(2*b - h[i-1])
else:
# handle i=0 case here
You are successively applying a function (equation) to the result of a previous application of that function - the process needs a seed to start it. Your result looks like this [seed, f(seed), f(f(seed)), f(f(f(seed)), ...]. This concept is function composition. You can create a generalized function that will do this for any sequence of functions, in Python functions are first class objects and can be passed around just like any other object. If you need to preserve the intermediate results use a generator.
def composition(functions, x):
""" yields f(x), f(f(x)), f(f(f(x)) ....
for each f in functions
functions is an iterable of callables taking one argument
"""
for f in functions:
x = f(x)
yield x
Your specs require a seed and a constant,
seed = 0
b = 10
The equation/function,
def f(x, b = b):
return 2*b - x
f is applied b times.
functions = [f]*b
Usage
print list(composition(functions, seed))
If the intermediate results are not needed composition can be redefined as
def composition(functions, x):
""" Returns f(x), g(f(x)), h(g(f(x)) ....
for each function in functions
functions is an iterable of callables taking one argument
"""
for f in functions:
x = f(x)
return x
print composition(functions, seed)
Or more generally, with no limitations on call signature:
def compose(funcs):
'''Return a callable composed of successive application of functions
funcs is an iterable producing callables
for [f, g, h] returns f(g(h(*args, **kwargs)))
'''
def outer(f, g):
def inner(*args, **kwargs):
return f(g(*args, **kwargs))
return inner
return reduce(outer, funcs)
def plus2(x):
return x + 2
def times2(x):
return x * 2
def mod16(x):
return x % 16
funcs = (mod16, plus2, times2)
eq = compose(funcs) # mod16(plus2(times2(x)))
print eq(15)
While the process definition appears to be recursive, I resisted the temptation so I could stay out of maximum recursion depth hades.
I got curious, searched SO for function composition and, of course, there are numerous relavent Q&A's.

Categories