Error using np.vectorize inside a function - python

I am trying to create a function called function2 that vectorize a function, it works when I only create one function, but if try to wrap it in another function I dont get the results that I need
this code works
A= np.array([1])
B= np.array([2])
def function1(a, b):
if a > b:
return a - b
else:
return a + b
function1 = np.vectorize(function1)
function1(A, B)
out array([3])
but this one does not and I dont know why, I am expecting to get the same result as the code above array([3])
def function1(a, b):
if a > b:
return a - b
else:
return a + b
def function2(a, b):
function2 = np.vectorize(function1)
return function2
function2(A, B)
out <numpy.vectorize at 0x24f0a22eba8>
thanks for the help in advance

That is because in the second case you are not calling the function you are just returning the function object. np.vectorise returns the function object but doesn’t call it.
Change your code to -
def function3(a, b):
function2 = np.vectorize(function1)
return function2(a,b) #call here
function3(A,B)
Should work now.
In the first case function2 is the vectorised function object itself and passing (A,B) parameters to it will call it.
In second case function2 is a parametric function but instead of using the parameters a,b it simple returns a function object. So when you call it with parameters, it overwrites function2 and returns a vectorised function object each time, completely ignoring the parameters all together.
In the third case (my solution) you are calling function3 which takes A,B parameters and first vectorises function1. Next it calls this vectorised function with the passed parameters and returns the output.
Follow the function calls and the sequential lines of code in your function and it will be super clear of why that is happening.

Related

How to update pure function?

I'm trying to do the following: I want to write a function translate(f, c) that takes a given function f (say we know f is a function of a single variable x) and a constant c and returns a new function that computes f(x+c).
I know that in Python functions are first-class objects and that I can pass f as an argument, but I can't think of a way to do this without passing x too, which kind of defeats the purpose.
The trick is for translate to return a function instance.
def translate(f, c):
def func(x):
return f(x + c)
return func
Now the variable x is "free", and the names f and c are coming from an enclosing scope.
What about this?
def translate_func(f, c):
return lambda x: f(x + c)
To be used like, e.g.:
import math
g = translate_func(math.sin, 10)
print(g(1) == math.sin(10 + 1))
# True
EDIT
Note that this design pattern of a function taking a function as a parameter and returning another function is quite common in Python and goes by the name of "function decoration", with an associated convenience syntax. See PEP318 for more info on it.
def transalte(f, c):
def _inner(x):
return f(x+c)
return _inner

how a function in python is getting called by just typing the name of function and not using brackets

First of all to find "lcm" of two numbers I made a function lcm(a, b). Then I thought of finding "hcf" too so I made a decorator decor and defined a function hcf(a, b) in it. And then I returned this function by just typing the name of the function and I didn't put brackets with it but it is still working. I cant understand why this function is working even though I didn't used brackets.
def decor(lcm_arg): # just to practice decorators
def hcf(a, b):
if a > b:
a, b = b, a
while True:
if b % a == 0:
print("hcf is", a)
break
else:
a, b = b % a, a
return lcm_arg(a, b)
return hcf # how hcf function is working without using brackets
#decor
def lcm(a, b):
if a > b:
a, b = b, a
for x in range(b, a*b+1, b):
if x % a == 0:
print("lcm is", x)
break
lcm(2, 4)
Output:
hcf is 2
lcm is 4
I don't think you understand decorators. Let's make a minimal example.
def my_decorator(some_function):
def new_function(*args, **kwargs):
'announces the result of some_function, returns None'
result = some_function(*args, **kwargs)
print('{} produced {}'.format(some_function.__name__, result))
return new_function # NO FUNCTION CALL HERE!
#my_decorator
def my_function(a, b):
return a + b
my_function(1, 2) # will print "my_function produced 3"
We have a simple function my_function which returns the sum of its two arguments and a decorator which will just print out the result of whatever function it decorates.
Note that
#my_decorator
def my_function(a, b):
return a + b
is equivalent to
def my_function(a, b):
return a + b
my_function = my_decorator(my_function)
Since my_decorator accepts a function as an argument (here we are giving it my_function) and returns a new function new_function (without calling it!), we effectively override my_function because we reassign the name to whatever my_decorator returns.
In action:
>>> my_function(1, 2)
my_function produced 3
Note that at every point in the example when a function is called, it happens with the parentheses-syntax. Here are all the function calls that happen in the first block of code I posted, in order:
my_decorator(my_function) is called and the return value is reassigned to the name my_function. This either happens through the # syntax or more explicitly in the equivalent code snippet.
my_function(1, 2) is called. At this point, my_function is the new_function that got returned by the decorator. Brain-parse it as new_function(1, 2).
Inside the body of new_function, the argument we gave to my_decorator is called (result = some_function(*args, **kwargs)) which happens to be the value of my_function before the reassignment that happened in step 1.
print is called.
If you want to understand how new_function is holding on to some_function despite my_decorator already having returned from its call, I suggest looking into the topics free variables and closures.
return hcf does not call the function because there are no parentheses, as you noticed. The decor function is used as a decorator which reassigns the name lcm to refer to the returned function. What I mean by this is that
#decor
def lcm(a, b):
// ...
is equivalent to
def lcm(a, b):
// ...
lcm = decor(lcm)
After this executes, lcm refers to the function hcf. So calling lcm(2, 4) now executes the code in hcf. I think the key here is to understand that at the line lcm(2, 4), lcm and hcf are two names which refer to the same function.

Function that returns a function that returns a function

I've been given this function. It returns the function pair that it also returns the function f I think. That is the part that tricks me, I don't know what f(a, b) is and how to use it.
def cons(a, b):
def pair(f):
return f(a, b)
return pair
To help you understand what is going on, consider the following example:
def cons(a, b):
def pair(f):
return f(a, b)
return pair
def my_func(a, b):
return a + b
# cons returns a function that takes a function arg and calls it with args (a, b),
# in this case (1, 3). Here a, b are considered "closured" variables.
apply_func = cons(1, 3)
print apply_func(my_func) # prints 4
Lets analyse this from inside out:
def cons(a, b):
def pair(f):
return f(a, b)
return pair
The innermost level is return f(a, b) - that obviously calls function f with arguments (a, b) and returns whatever the result of that is.
The next level is pair:
def pair(f):
return f(a, b)
Function pair takes a function as an argument, calls that function with two arguments (a, b) and returns the result. For example:
def plus(x, y):
return x + y
a = 7
b = 8
pair(plus) # returns 15
The outermost level is cons - it constructs function pair which has arbitrary a and b and returns that version of pair. E.g.
pair_2_3 = cons(2,3)
pair_2_3(plus) # returns 5, because it calls plus(2, 3)
. . . I don't know what f(a, b) is and how to use it.
f(a, b) is simply a function call. All the code you provided does is define a function that returns a function. The function returned from the first function, itself returns a function. I assume the way it would be used is perhaps something like:
>>> cons(1, 2)(lambda x, y: x + y)
3
>>>
The above code would be equivalent to:
>>> pair_func = cons(1, 2) # return the `pair` function defined in `cons`
>>> f = lambda x, y: x + y
>>> pair_func(f) # apply the `f` function to the arguments passed into `cons`.
3
>>>
It might also help to note that the pair function defined in this case, is what's know as a closure. Essentially, a closure is a function which has access to local variables from an enclosing function's scope, after the function has finished execution. In your specific case, cons is the enclosing function, pair is the closure, and a and b are the variables the closure is accessing.
Well if you could share the complete question then we might be able to help you better. Meanwhile what I can tell you here is that in the return of pair(f) the program is calling a function f which takes two arguments a and b. This function f(a,b) is called and then its value will be returned to pair(f).
But the point to note here is that in pair function we already have a local variable f, so when we will try to call the function f(a,b) it will give us UnboundedLocalVariable error. Therefore, we will need to change the name of this function from f to something else.

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

Which object does name "g" bind to?

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.

Categories