When my function foo generating a new element, I want to reuse the output and put it in foo n-times. How can I do it?
My function:
def foo(x):
return x + 3
print(foo(1))
>>>4
For now. I'm using this method:
print(foo(foo(foo(1))))
There are a couple ways to do what you want. First is recursion, but this involves changing foo() a bit, like so:
def foo(x, depth):
if depth <= 0:
return x
return foo(x+3, depth-1)
and you'd call it like foo(1, n)
The other way is with a loop and temp variable, like so
val = 1
for _ in range(0, n):
val = foo(val)
Use a loop for this:
value = 1
for i in range(10):
value = foo(value)
def foo(x,y):
for i in range(y):
x = x + 3
return x
print (foo(10,3))
Output:
19
What you are searching for is called recursion:
def foo(x, n=1):
if n == 0:
return x
return foo(x + 3, n - 1)
Another possible with lambda and reduce
Reduce function
from functools import reduce
def foo(x):
return x + 3
print(reduce(lambda y, _: foo(y), range(3), 1))
You will get 10 as result
# y = assigned return value of foo.
# _ = is the list of numbers from range(3) for reduce to work
# 3 = n times
# 1 = param for x in foo
Related
I know how to compose two functions by taking two functions as input and output its composition function but how can I return a composition function f(f(...f(x)))? Thanks
def compose2(f, g):
return lambda x: f(g(x))
def f1(x):
return x * 2
def f2(x):
return x + 1
f1_and_f2 = compose2(f1, f2)
f1_and_f2(1)
You use a loop, inside a nested function:
def compose(f, n):
def fn(x):
for _ in range(n):
x = f(x)
return x
return fn
fn will be have closure that retains references to the f and n that you called compose with.
Note this is mostly just copied from https://stackoverflow.com/a/16739439/2750819 but I wanted to make it clear how you can apply it for any one function n times.
def compose (*functions):
def inner(arg):
for f in reversed(functions):
arg = f(arg)
return arg
return inner
n = 10
def square (x):
return x ** 2
square_n = [square] * n
composed = compose(*square_n)
composed(2)
Output
179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216
if you want to make it one line composition,
then try this,
def f1(x):
return x * 2
def f2(x):
return x + 1
>>> out = lambda x, f=f1, f2=f2: f1(f2(x)) # a directly passing your input(1) with 2 function as an input (f1, f2) with default so you dont need to pass it as an arguments
>>> out(1)
4
>>>
>>> def compose(f1, n):
... def func(x):
... while n:
... x = f1(x)
... n = n-1
... return x
... return func
>>> d = compose(f1, 2)
>>> d(2)
8
>>> d(1)
4
>>>
you can use functools.reduce:
from functools import reduce
def compose(f1, f2):
return f2(f1)
reduce(compose, [1, f2, f1]) # f1(f2(1))
output:
4
if you want to compose same function n times:
n = 4
reduce(compose, [1, *[f1]*n]) # f1(f1(f1(f1(1))))
output:
16
I would like to create a new function that has two inputs (n, input_function) which returns a new output_function that does what input_function does but it does it n times. Here is the image of what i'm trying to accomplish
def repeat_function(n, function, input_number):
for i in range(n):
input_number = function(input_number)
return input_number
def times_three(x):
return x * 3
print(repeat_function(3, times_three, 10)) #prints 270 so it's correct
print(times_three(times_three(times_three(10)))) #prints 270 so it's correct
#This function does not work
def new_repeat_function(n, function):
result = lambda x : function(x)
for i in range(n-1):
result = lambda x : function(result(x))
return result
new_function = new_repeat_function(3, times_three)
#I want new_function = lambda x : times_three(times_three(times_three(x)))
print(new_function(10)) # should return 270 but does not work
I tried my best to implement it but it does not work. I need new_repeat_function to do what repeat_function does but instead of returning and integer answer like repeat_function does, new_repeat_function has to return time_three() n times.
You need to return a function, not the result.
def new_repeat_function(n, function):
def repeat_fn(x):
result = function(x)
for i in range(n - 1):
result = function(result)
return result
return repeat_fn
Here, you construct a closure that captures the parameters n and function. Later, when you call the returned closure, it uses n and function as they were passed to new_repeat_function. So, if we call
new_func = new_repeat_function(3, three_times)
print(new_func(10))
we get 270 as expected.
What you need to do is to create a function that builds another function, in python this pattern is called decorators, here you have an example:
from functools import wraps
def repeated(n):
def wrapped(f):
#wraps(f)
def ret_f(*args, **kwargs):
res = f(*args, **kwargs)
for _ in range(1, n):
res = f(res)
return res
return ret_f
return wrapped
#repeated(2)
def times_three(x):
return x * 3
print(times_three(10))
You can try it live here
You can simply recur on repeat itself. Ie, you don't need to create a range or use a loop at all
def repeat (n, f):
return lambda x: \
x if n is 0 else repeat (n - 1, f) (f (x))
def times_three (x):
return x * 3
new_func = repeat (3, times_three)
print (new_func (10))
# 270
You can skip intermediate assignments as well
print (repeat (0, times_three) (10))
# 10
print (repeat (1, times_three) (10))
# 30
print (repeat (2, times_three) (10))
# 90
x = 5
def SsolGom():
k = 1
for i in range( 1 , x+1 ):
k = k * i
print(SsolGom)
=function SsolGom at 0x00F1B660
120 must come out but strange value came out...
SsolGom is a function, SsolGom() is the value returned by this function. It's similar in math: sin is a function, sin(0) is a number.
x = 5
def SsolGom():
k = 1
for i in range( 1 , x+1 ):
k = k * i
return k
print(SsolGom())
# 120
You need to have a correct indentation inside your function, and you need to return a value. SsolGom() would be None otherwise.
Note that x probably shouldn't be a global variable. Otherwise, your function could be replaced by return 120:
def factorial(x):
k = 1
for i in range(x):
k = k * (i + 1)
return k
print(factorial(5))
Finally, here's the easiest way to get factorial in Python:
>>> from math import factorial
>>> factorial(5)
120
You're missing the brackets. It should be:
print(SsolGom())
You are printing the function without the parenthesis. Calling a function with and without parenthesis gives different results in Python. If you do not provide a parenthesis, Python considers it as properties and not a method/function. Hence you got that result
provide a return statement in the function.
Updated Code:
x=5
def SsolGom():
k=1
for i in range( 1 , x+1 ):
k=k*i
return k
print(SsolGom())
def fib(a, b, f):
fib must generate (using yield) the generalized Fibonacci
sequence, a and b is first and second element. f is function to get the third element instead of a+b as normal Fibonacci sequence. Use take function(which show below) to test it.
my code is below
def fib(a, b, f):
x = a
y = b
yield x
x, y = y, f(x,y)
fib(x,y,f)
I don't know what is wrong of my code, when I try to test it, it show
"TypeError: 'generator' object is not subscriptable"
the test case is:
take(5, fib(0, 1, lambda x, y: x - y))
It should out put:
[0, 1, -1, 2, -3]
and take function as i write is :
def take(n, iterable):
x = []
if n <= 0:
return x
else:
for i in range (0,n):
x.append(iterable[i])
return x
The message means that generators do not support indexing, so iterable[i] fails. Instead, use the next() function to get the next item from the iterator.
def take(n, iterable):
x = []
if n > 0
itr = iter(iterable) # Convert the iterable to an iterator
for _ in range(n): # Repeat n times
x.append(next(itr)) # Append the next item from the iterator
return x
Also, your fib() function will not work. You should not recurse at the end of the function; instead write a loop that yields a value each iteration.
def fib(a, b, f):
x = a
y = b
while True:
yield x
x, y = y, f(x,y)
You can't index into the results coming from a generator function like fib(). This following avoids that by using zip() with a range() argument. zip() stops automatically when one of its arguments reaches then end.
def fib(a, b, f):
x, y = a, b
while True:
yield x
x, y = y, f(x, y)
def take(n, iterable):
return [] if n <= 0 else [v for _, v in zip(range(n), iterable)]
print( take(5, fib(0, 1, lambda x, y: x-y)) )
Output:
[0, 1, -1, 2, -3]
Fibonacci simplest method you'll ever come across:
a , b =0 , 1
for n in range(100):#any number
print(a)
a = a + b
print (b)
b = b + a
def fibo(n):
if n == 0:
return 0
elif n == 1:
return 1
else:
return fibo(n - 1) + fibo(n - 2)
n = int(input("enter the number: "))
for i in range(n):
print(fibo(i))
I'm stuck at higher-order functions in python. I need to write a repeat function repeat that applies the function f n times on a given argument x.
For example, repeat(f, 3, x) is f(f(f(x))).
This is what I have:
def repeat(f,n,x):
if n==0:
return f(x)
else:
return repeat(f,n-1,x)
When I try to assert the following line:
plus = lambda x,y: repeat(lambda z:z+1,x,y)
assert plus(2,2) == 4
It gives me an AssertionError. I read about How to repeat a function n times but I need to have it done in this way and I can't figure it out...
You have two problems:
You are recursing the wrong number of times (if n == 1, the function should be called once); and
You aren't calling f on the returned value from the recursive call, so the function is only ever applied once.
Try:
def repeat(f, n, x):
if n == 1: # note 1, not 0
return f(x)
else:
return f(repeat(f, n-1, x)) # call f with returned value
or, alternatively:
def repeat(f, n, x):
if n == 0:
return x # note x, not f(x)
else:
return f(repeat(f, n-1, x)) # call f with returned value
(thanks to #Kevin for the latter, which supports n == 0).
Example:
>>> repeat(lambda z: z + 1, 2, 2)
4
>>> assert repeat(lambda z: z * 2, 4, 3) == 3 * 2 * 2 * 2 * 2
>>>
You've got a very simple error there, in the else block you are just passing x along without doing anything to it. Also you are applying x when n == 0, don't do that.
def repeat(f,n,x):
"""
>>> repeat(lambda x: x+1, 2, 0)
2
"""
return repeat(f, n-1, f(x)) if n > 0 else x