Basic functions in python 3.x - python

I don't get the second function can someone help me what does the second function do I got this in solo learn Please explain to me in very basic way as I am a beginner and
def add(x, y):
return x + y
def do_twice(func, x, y):
return func(func(x, y), func(x, y))
a = 5
b = 10
print(do_twice(add, a, b))

Python supports higher order programming: you can pass a function as an argument (actually Python does not care about the type when you pass arguments).
So what happens if you call do_twice(add, a, b)? Well you call do_twice with function = add, x = 5 and y = 10. Now we inspect the body of do_twice:
return func(func(x,y),func(x,y))
The Python interpreter will interpret this statement, and first evaluate func(x,y) (the left one). So it calls add(5,10). I assume that you understand how the add function works, so that function returns 15. Next Python evaluates func(x,y) (the right one), so it again calls add(5,10) which evaluates in 15.
Finally it calls func(15,15), since func = add, it thus calls add(15,15) which will result in 30. This is the result that is returned.
If you would have called do_twice with a lambda expression like:
do_twice(lambda x,y: x+2*y,5,10)
the result will thus be: 75. Because (lambda x,y:x+2*y)(5,10) is 25 and (lambda x,y:x+2*y)(25,25) is 75.

You could also write your second function like this:
def do_twice(func, x, y):
val1 = func(x, y)
val2 = func(x, y)
val3 = func(val1 , val2)
return val3
That way you are basically just storing the result of each of the 3 calls to func in a temporary variable (val1, val2, val3).
Now if you call print(do_twice(add, a, b)) with your values 5 and 10 the following happens:
def do_twice(func, x, y):
# x = 5, b = 10
val1 = func(x, y)
# val1 = 5+10 = 15
val2 = func(x, y)
# val2 = 5+10 = 15
val3 = func(val1, val2)
# val3 = 15+15 = 30
return val3

The second simply takes the first function and applies the supplied inputs to it. Such that do_twice takes a function called func. func requires two positional arguments to work an example of a func is add() that requires x and y. so do_twice() takes add() and supplies x and y to it then returns the answer. do_twice is hence returning add(add(x, y), add(x, y))

Related

How come the order of parameters doesn't matter in this function?

Why it seems that in check() function it doesn't matter if I pass the parameters as check(x,y) or check(y,x)?
I tried shifting x and y to see if it would give me a different output
import random
def guess(a, b):
x = random.randint(a, b)
return x
def check(a, b):
if y**2 == x:
print(x)
print(y)
return True
else:
return False
x = 100
left, right = 0, x
y = guess(left, right)
while not check(x, y):
y = guess(left, right)
print("answer", y)
I think you're making a salad between (a,b) and (x,y).
Your function check uses the "global" (from the outer scope) x and y and not the (x,y) you pass it in the call check(x,y).
Maybe you meant to use a and b instead of x and y inside the definition of check.
You function expects to get 2 arguments as your signature suggests (def check(a, b):) but then nowhere inside it you actually use those arguments. Instead you use x and y. This does not raise an error because Python looks in the outer scopes for those variables and finds them. If you want the order to matter you should change to:
def check(a, b):
if b**2 == a:
print(a)
print(b)
return True
else:
return False

Python pathos mutiprocessing, one list and one object as arguments

I want to use multiprocessing to accelerate multiple calls to a function, the function takes as argument two values, a variable that changes for every calculation and a constant variable.
Here is a code that emulates my problem:
import pathos.pools as pp
p = pp.ProcessPool(4)
def add(x,y):
return x+y
x = [0,1,2,3]
y = 5
result = p.map(add, x, y)
As y is not a list I get the following error:
TypeError: izip argument #2 must support iteration
In this simple case the straightforward solution would be to make y a list of the constant values:
y = [5 for value in x]
But I would like to avoid this solution as in my case y is a complex object that takes up quite a big chunk of memory.
Thanks for any suggestions
you can just use local variables for the function you declare. I often make a wrapper to pass non-iterables, e.g.
def add(x,y):
return x+y
def add_wrapper(x):
y = 5
return add(x,y)
x = [0,1,2,3]
result = p.map(add_wrapper, x)
or
def add(x,y):
return x+y
def add_wrapper(x):
return add(x,y)
y = 5
x = [0,1,2,3]
result = p.map(add_wrapper, x)

Why is this output 30 in python?

Can someone explain why this code of python outputs 30? It seems like add = func ? But how does python knows this without declaring. It's a question in the python course from sololearn.com, a lot of people don't seem to understand
def add(x, y):
return x + y
def do_twice(func, x, y):
return func(func(x, y), func(x, y))
a = 5
b = 10
print(do_twice(add, a, b))
def do_twice(func, x, y):
return func(func(x, y), func(x, y))
when called with add, 5 and 10 will return
add(add(5, 10), add(5, 10))
i.e.
add(15, 15)
which is indeed 30
add has been passed as the first parameter, so is called func inside do_twice. Likewise a is 5 and b is 10.
A is set to 5 and B to 10. This add function simply returns the sum of two inputs.
You call do_twice with the add function, 5, and, 10 as inputs.
First, do_twice evaluates the sum of 5 and 10 in both inner calls of func(x, y). This leaves us with "return func(15, 15)". This adds 15 and 15, yielding 30. Finally, you print out this value. This is why it is 30. Feel free to follow up for any clarifications!
Python don't care what you pass in for func for your function do-twice.
But in the body of your function do_twice you are invoking func passed in i.e You are using func as if it supposed to be a callable(something you can invoke. A function is one such thing.). You can verify it by passing a string to do_twice and you should see an error stating string is not callable or something.

Function Calling With 3 or More Argument Input Fields - function()()()

I am studying the properties of functions in Python and I came across an exercise that asks to:
Write a function which returns de power of a number. Conditions: The function may only take 1 argument and must use another function to return the value of the power of a given number.
The code that solves this exercise is:
def power(x):
return lambda y: y**x
For example, if we would like to know the value of the power: 2^3, we would call the function like this: power(3)(2)
Here is what I would like to know:
Is there any way to write a function that, when called, has a similar structure: function()()().
In other words, is it possible to write a function, that requires three or more parentheses ()()() when called?
If it is possible, could you please give me an example code of that function and briefly explain it?
Also:
def power(x):
def power_extra(y):
return y
def power_another(z):
return z
return power_extra and power_another
Possible?
Sure you can:
def power_times(k):
"""use as power_times(k)(x)(y) => k * y^x"""
return lambda x: lambda y: k * y**x
print power_times(2)(3)(4) # returns 2 * 4^3 = 128
When you call this function with argument 2 (power_times(2)), it returns a lambda function that works like lambda x: lambda y: 2 * y ** x (that is, like your original function, only with an extra "times 2").
You can stack as many lambdas on top of each other as you like:
def many_lambdas(x):
"""many_lambdas(x)(y)(z)(q) => x + y * z^q"""
return lambda y: lambda z: lambda q: x + y * z ** q
print many_lambdas(1)(2)(3)(4) # prints 163
Indeed, it might be even clearer if you skipped using def at all, and just wrote:
many_lambdas = lambda x: lambda y: lambda z: lambda q: x + y * z ** q
Or, alternatively, you could skip using lambda ever and just use them as nested functions:
def many_funcs(x):
def many_funcs_y(y):
def many_funcs_z(z):
def many_funcs_q(q):
return x + y * z ** q
return many_funcs_q
return many_funcs_z
return many_funcs_y
print many_funcs(1)(2)(3)(4) # prints 163
#David's answer would aptly answer you question for fixed nested function calls. For undefined nesting, you may want to define a class and overload the __call__ method along with __repr__ and __int__ to serve your Purpose.
>>> class Power(object):
def __init__(self, value):
self.value = value
def __call__(self, value):
self.value **= value
return self
def __int__(self):
return self.value
def __repr__(self):
return str(self.value)
>>> print Power(2)(2)(2)(2)(2)
65536
>>> int(Power(2)(2)(2)(2)(2)) / 2
32768

Passing functions with arguments to another function in Python? [duplicate]

This question already has answers here:
Python function as a function argument?
(10 answers)
Python Argument Binders
(7 answers)
Closed 5 months ago.
Is it possible to pass functions with arguments to another function in Python?
Say for something like:
def perform(function):
return function()
But the functions to be passed will have arguments like:
action1()
action2(p)
action3(p,r)
Do you mean this?
def perform(fun, *args):
fun(*args)
def action1(args):
# something
def action2(args):
# something
perform(action1)
perform(action2, p)
perform(action3, p, r)
This is what lambda is for:
def perform(f):
f()
perform(lambda: action1())
perform(lambda: action2(p))
perform(lambda: action3(p, r))
You can use the partial function from functools like so.
from functools import partial
def perform(f):
f()
perform(Action1)
perform(partial(Action2, p))
perform(partial(Action3, p, r))
Also works with keywords
perform(partial(Action4, param1=p))
Use functools.partial, not lambdas! And ofc Perform is a useless function, you can pass around functions directly.
for func in [Action1, partial(Action2, p), partial(Action3, p, r)]:
func()
This is called partial functions and there are at least 3 ways to do this. My favorite way is using lambda because it avoids dependency on extra package and is the least verbose. Assume you have a function add(x, y) and you want to pass add(3, y) to some other function as parameter such that the other function decides the value for y.
Use lambda
# generic function takes op and its argument
def runOp(op, val):
return op(val)
# declare full function
def add(x, y):
return x+y
# run example
def main():
f = lambda y: add(3, y)
result = runOp(f, 1) # is 4
Create Your Own Wrapper
Here you need to create a function that returns the partial function. This is obviously lot more verbose.
# generic function takes op and its argument
def runOp(op, val):
return op(val)
# declare full function
def add(x, y):
return x+y
# declare partial function
def addPartial(x):
def _wrapper(y):
return add(x, y)
return _wrapper
# run example
def main():
f = addPartial(3)
result = runOp(f, 1) # is 4
Use partial from functools
This is almost identical to lambda shown above. Then why do we need this? There are few reasons. In short, partial might be bit faster in some cases (see its implementation) and that you can use it for early binding vs lambda's late binding.
from functools import partial
# generic function takes op and its argument
def runOp(op, val):
return op(val)
# declare full function
def add(x, y):
return x+y
# run example
def main():
f = partial(add, 3)
result = runOp(f, 1) # is 4
(months later) a tiny real example where lambda is useful, partial not:
say you want various 1-dimensional cross-sections through a 2-dimensional function,
like slices through a row of hills.
quadf( x, f ) takes a 1-d f and calls it for various x.
To call it for vertical cuts at y = -1 0 1 and horizontal cuts at x = -1 0 1,
fx1 = quadf( x, lambda x: f( x, 1 ))
fx0 = quadf( x, lambda x: f( x, 0 ))
fx_1 = quadf( x, lambda x: f( x, -1 ))
fxy = parabola( y, fx_1, fx0, fx1 )
f_1y = quadf( y, lambda y: f( -1, y ))
f0y = quadf( y, lambda y: f( 0, y ))
f1y = quadf( y, lambda y: f( 1, y ))
fyx = parabola( x, f_1y, f0y, f1y )
As far as I know, partial can't do this --
quadf( y, partial( f, x=1 ))
TypeError: f() got multiple values for keyword argument 'x'
(How to add tags numpy, partial, lambda to this ?)
Although all the responses are very accurate and well explained.
I want to make a clarification that you also can pass anonymous functions.
def perform(fun, *arg):
return fun(*arg)
# Pass anonymous function
print(perform(lambda x: x + 1, 3)) # output: 4
print(perform(lambda x, y: x + y + 1, 3, 2)) # output: 6
# Pass defined function
perform(lambda: action1())
perform(lambda: action2(p))
perform(lambda: action3(p, r))
Here is a way to do it with a closure:
def generate_add_mult_func(func):
def function_generator(x):
return reduce(func,range(1,x))
return function_generator
def add(x,y):
return x+y
def mult(x,y):
return x*y
adding=generate_add_mult_func(add)
multiplying=generate_add_mult_func(mult)
print adding(10)
print multiplying(10)
I think this is what you're looking for...
def action1(action):
print(f'doing {action} here!')
def perform(function):
return function()
perform(lambda : action1('business action'))
lambda packages up func and args in closure and passes to perform()
Thanks to David Beasley.

Categories