How does this python factory function work [duplicate] - python

This question already has answers here:
Can you explain closures (as they relate to Python)?
(13 answers)
Closed 2 years ago.
This is the python function from my pluralsight python class:
def raise_to(exp):
def raise_to_exp(x):
return pow(x, exp)
return raise_to_exp
And the instructor now opens an interactive session and does the following:
from raise_to import raise_to
square = raise_to(2), and then goes on to do
square(5)
and that produces the result of 25. How or why pass in two distinct arguments? Now I ran a debug on this code and this is what I observed. When I do this:
def raise_to(exp):
def raise_to_exp(x):
return pow(x, exp)
return raise_to_exp
square = raise_to(2)
print(square)
I get : <function raise_to.<locals>.raise_to_exp at 0x00000246D1A88700>, but if I do as the instructor
def raise_to(exp):
def raise_to_exp(x):
return pow(x, exp)
return raise_to_exp
square = raise_to(2)
print(square(5))
I get 25. I would like to know how this works. I know this is referred as a python factory function but how does it work. Is the function storing the first argument for later use with the second argument passed in?

raise_to_exp is a closure over the parameter exp defined by raise_to. When you call raise_to(2), you get back a function in whose body the variable exp refers to the variable in the scope where raise_to_exp was defined.
This means that square is a function where exp is bound to 2, so roughly equivalent to the definition
def square(x):
return pow(x, 2)
Just to prove that there was no replacement of exp with the value 2, you can do a bit of digging into the function object to change the value of exp.
>>> square(5)
25
>>> square.__closure__[0].cell_contents = 3 # now square is cube!
>>> square(5)
125

def raise_to(exp):
def raise_to_exp(x):
return pow(x, exp)
return raise_to_exp
I made the last statement bold. You're returning a function here. Think of it as
a=lambda x:x+1
a(1)
# 2
When you do
square=raise_to(2)
Now square refers to the function raise_to_exp because raise_to returned the raise_to_exp function. square can be used as a function here.
square(2) # with exp set as 2
# 4
cube=raise_to(3)
cube(2)
# 8

Related

What is the logic behind this example?

def myfunc(n):
return lambda a : a * n
mytripler = myfunc(3)
print(mytripler(11))
I am trying to learn about the lambda function in python. I understand the other examples given inside w3schools about the Lambda function. This example, however, I could not wrap my head around. How is it that mytripler(11) multiplies 3 by 11?
Note that there is nothing particularly special about lambda. It's just a convenient method of creating an anonymous function.
If the code had instead been written:
def myfunc(n):
def inner(a):
return a * n
return inner
It would be the exact same thing. Except now we've given anonymous function a name inner. But you'd discover that you can still write mytripler = myfunc(3) and it works the same way.
Python understands closures. If a variable is used (but not modified) inside an inner function, and there is an identically named variable defined in a containing function, then Python realizes that the inner variable refers to whatever value that outer variable has.
Let's take a step back: What is a function?
One definition could be that's a construct where you give it arguments, it does something and it returns a value (Let's ignore for now the cases where you don't give any arguments or where you don't receive any return value)
In Python, since everything is an object, this kind of construct is a value that can be assigned a name. For example:
>>> def example_function(argument):
... result = argument * 42
... return result
...
>>> other_name_for_example_function = example_function
>>> example_function(3)
126
>>> other_name_for_example_function(3)
126
>>> example_function == other_name_for_example_function
True
>>> example_function is other_name_for_example_function
True
Note that in the comparison made at the end, I do not call these functions, I just compare the value of example_function and other_name_for_example_function which in this case is the same "function mechanism".
Now, lambdas are another way to define a function but it's more restricted and the function isn't assigned a name automatically. Let's take the same example but with lambdas:
>>> example_lambda = lambda argument: argument * 42
>>> other_name_for_example_lambda = example_lambda
>>> example_lambda(3)
126
>>> other_name_for_example_lambda(3)
126
>>> example_lambda == other_name_for_example_lambda
True
>>> example_lambda is other_name_for_example_lambda
True
Now if we replace the function call of your example with its content, it would look like this:
>>> n = 3 # just you see where that value will be used
>>> mytripler = lambda a: a * n
>>> a = 11 # also to see where that value will be used
>>> mytripler(a)
33
So, in your example,
myfunc() provide a "function mechanism" as a return value. In the definition of that "function mechanism", you have inserted the value 3 which is an argument of myfunc()
You assign the name mytripler to that function returned
You call it like you would with any function
Does that help you understand?

Returning Nested Functions in Python

def raise_val(n):
"""Return the inner function."""
def inner(x):
"""Raise x to the power of n."""
raised = x ** n
return raised
return inner
square = raise_val(2)
cube = raise_val(3)
print(square(2), cube(4))
Outputs:
4 64
Can anybody explain to me how come square(2) knows that the argument passed is x?
this code uses the concept of lexical closures or closures.Closures are the function that remembers the parameters passed to their parent function.The more technical definition will be,Closures are the function that remembers values in enclosing scope even if they are not actually present in the memory.
#for example`
def outer(x):
def inner():
print(f"The argument passed to outer was {x}")
'''Notice how inner() will grab the argument passed to the outer function'''
return inner
value=outer(69)
print(value())
Maybe this will help: https://stackabuse.com/python-nested-functions/
Notice you "sends arguments twice" (not really): first in square = raise_val(2) and second in square(2). What happens? The first calls return a function: you call to raise_val and it returns inner, which is a function. Now square variable actually holds a function. Second call, square(2), just call to the function.
It's the same as:
def a(x):
print(x)
square = a
print(square(5))
In this example, square holds a function. It's the same as in your code, since raise_val returns a function. Square holds inner method, and later it is been called. You send x directly: square(2) sends 2 for x of course.
A more interesting can be "how inner remembers n?", and as others mentioned in comments: it's manages variables of current scope.

<function output at 0x> when calling function [duplicate]

This question already has an answer here:
Python <function at 0x> output [duplicate]
(1 answer)
Closed 3 years ago.
def num(num1, num2):
def adder(num):
return (num1 + num2)
return adder()
num(5, 6)
When I type this code in i get the output of < function num..adder at 0x10b83bdd0 >, and I'm not entirely sure what I'm doing wrong. How do I get it to return 11?
num returns a function, so you need to call it:
num(5, 6)(0) # the number you call it with is irrelevant since you never use num in adder
# 11
In this case this approach is kind of useless. This is usually done if you want to define a partial function or a "function factory", for example:
def multiplier(multiply_by):
def inner(n):
return multiply_by * n
return inner
multiply_by_2 = multiplier(2)
multiply_by_4 = multiplier(4)
print(multiply_by_2(4))
print(multiply_by_4(4))
Outputs
8
16
Your example would have made more sense if the argument was actually used in the inner function, then this becomes very similar to my example above but using addition instead of multiplication:
def adder(num1):
def inner(num2):
return num1 + num2
return inner
two_adder = adder(2)
three_adder = adder(3)
print(two_adder(2))
print(three_adder(2))
Outputs
4
5
You return the adder function, but you don't call it.
The function returns another function. If you want a number, you need to call the returned function as well:
f = adder(1, 2)
print(f(4)) # Call the returned f
Although the second call is useless since you never make use of num.

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.

Nested function(Python 3)

a function (funcA) that takes a function (funcB) and returns a function that can be evaluated to produce the same value that funcB would produce (if given the same arguments) plus 1
returned_func(x) = funcB(x) + 1
What could be the possible way of doing this? I am confused with the second part of the question as to how can a function return a value and function at the same time. Any code example would be much appreciated! Thanks!
The concept you're looking for is, essentially, a function decorator. In Python, functions are first-class objects, just like class instances are in other languages. That means that you can pass them around, just like any other object. For example:
def foo(x):
return x + 1
print(foo) # <function foo at 0x0000024202F43EA0>
bar = foo
print(bar) # <function foo at 0x0000024202F43EA0>
Here we created a reference to the function object itself. We can, using the same idea, make a function which returns a function:
def foo(x):
def inner(y):
return x + y
return inner
func = foo(5)
print(func(3)) # 8
func is assigned to the return value of foo, which is itself a function that we can evaluate. You want to return a function A that adds 1 to the result of another function, B. So, pass B to a function make_A:
def make_A(b):
def inner(x):
return b(x) + 1
return inner
def B(x):
return x
A = make_A(B)
print(A(1)) # 2
Python has excellent syntactic sugar for this type of function. See this primer for more information.
def func1(x):
#operations go here:
return(x + 1)
def func2():
#operations go here:
return(x - 1)
if func1(2) == func2(4):
print("Hooray")
Does this help? It is a demonstration of how parameters and return values can interact.
A segment like func(1) implies the return value with the parameter as 1.

Categories