Why in the following code, the output is 22?
In my understanding, we have a function that needs two arguments, but it has been defined with only one! However, the first time we use it in mydoubler = myfunc(2), it assigns the argument(2) to variable n, but the second time we use it in print(mydoubler(11), it uses the argument(11) to set the value of the variable a! Why is that? Does Lambda work like a recursive function?
def myfunc(n):
return lambda a : a * n
mydoubler = myfunc(2)
print(mydoubler(11))
Basically what happens is this:
mydoubler = myfunc(2) is actually the same as writing mydoubler = lambda a : a * 2
The reason for this is that myfunc(2) returns lambda a : a * 2
So now mydoubler = lambda a : a * 2
Then when mydoubler(11) is called, it simply returns 11 * 2
You're returning a lambda, which is a one-liner function, NOT a number. The code below does the EXACT SAME thing, but is maybe a bit clearer as to its purpose:
def multiplier_factory(constant_factor):
# Define our new function
def multiplier(factor):
result = constant_factor * factor
return result
# Return the FUNCTION, not a number
return multiplier
doubler = multiplier_factory(2)
tripler = multiplier_factory(3)
print (doubler(1)) # prints 2
print (tripler(1)) # prints 3
print (doubler('a')) # prints 'aa'
print (tripler('a')) # prints 'aaa'
lambda a: a * n is the same of:
def somefunction(a):
return a * n
When you called myfunc(2) you dynamically created a function that is the same of:
def somefunction(a):
return a * 2
myfunc returns a function. So mydoubler is a function and is described by lamda a : a * 2. Then you call that function with the argument 22 and so naturally 11 * 2 = 22 is printed. Lambda functions are not per se recursive, they are just a shorter way of writing a simple function. In your case you can also write:
def myfunc(n):
def multiplier(a):
return a * n
return multiplier
Related
CASE 1: ERROR output
def myfunc(n):
return lambda a : a * n
mytripler(11) = myfunc(3) => Error
===========================================
CASE 2: Correct output
def myfunc(n):
return lambda a : a * n
mytripler = myfunc(3)
print(mytripler(11))
How does the value 11 get passed to the method in the second case?
When myfunc is executed it is returning another function...
def myfunc(n):
Return lambda x : x*n
Is same as writing..
def myfunc(n):
def f(x):
Return x*n
return f
Hence in first function you are returning another function and as it has formed closure it has access to n variable of parent function.
It is because of the way lambda functions work, the value 11 is used in place of the variable 'a' in your case and n is already 3.
When mytripler = myfunc(3) is ran, it is returning a function(lambda) which looks like
def fun(a) :
return a * 3
Now the mytripler points to the above function "fun" which takes a single argument and multiplies it by 3.
Your function myfunc returns a function/callable (in this case lambda function), as can be seen here:
>>> def myfunc(n):
... return lambda a : a * n
>>> print(myfunc)
<function myfunc at 0x7efe15c9dea0>
Now, when we make the call to myfunc, the value passed as n will be bound in the lambda function:
>>> mytripler = myfunc(3)
>>> print(mytripler)
<function myfunc.<locals>.<lambda> at 0x7efe14f20598>
At this point mytripler is defined as lambda a : a * 3; the n was replaced by the value (or also: has been assgined the value) that we passed as argument to myfunc(). Note that this lambda construct is functionally equivalent to:
>>> def mytripler(a):
... return a * 3
Now, we can call mytripler with an value to make the final calculation/execution:
>>> mytripler(11)
33
Your error is that you cannot assign a value to a function call on the left-hand side:
>>> mytripler(11) = myfunc(3)
File "<input>", line 1
SyntaxError: can't assign to function call
But you can skip the intermediary step of assigning the result of myfunc to the name mytripler, and instead do both function calls chained together, like this:
>>> myfunc(3)(11)
33
Does that answer your question?
Imagine there are three functions, all them accept and return the same type args.
Normally, we can write it as fun3(fun2(fun1(args)), this can be say that a sequence function act on parameter in order, which likes one variety Higher-order functions "map".
You know in Mathematica, we can write this as fun3#fun2#fun1#args.
Now the question is that can we integrate fun3#fun2#fun1 as another fun without modifying their definition, so fun(args) can replace fun3(fun2(fun1(args)), this looks more elegant and concise.
def merge_steps(*fun_list):
def fun(arg):
result = arg
for f in fun_list:
result = f(result)
return result
return fun
def plus_one(arg):
return arg + 1
def double_it(arg):
return arg ** 2
def power_ten(arg):
return arg ** 10
combine1 = merge_steps(power_ten, plus_one, double_it)
combine2 = merge_steps(plus_one, power_ten, double_it)
combine1(3)
> 3486902500
or use lambda:
steps = [power_ten, plus_one, double_it]
reduce(lambda a, f: f(a), steps, 3)
> 3486902500
I think you can use Function Recursion in python to do this.
def function(args, times):
print(f"{times} Times - {args}")
if times > 0 :
function(args,times - 1)
function("test", 2)
Note: I just add times argument to not generate infinite loop.
I'm not certain I understand your question, but are you talking about function composition along these lines?
# Some single-argument functions to experiment with.
def double(x):
return 2 * x
def reciprocal(x):
return 1 / x
# Returns a new function that will execute multiple single-argument functions in order.
def compose(*funcs):
def g(x):
for f in funcs:
x = f(x)
return x
return g
# Demo.
double_recip_abs = compose(double, reciprocal, abs)
print(double_recip_abs(-2)) # 0.25
print(double_recip_abs(.1)) # 5.0
I'm looking for a way to change the variables defined inside a function after defining the function.
For example
def GetNthPower(x) :
n = None
return x**n
my_numbers_list = [11,23,45,56,78,98]
# now if I feel like I need the 4th power of some numbers in the list
GetNthPower.n = 4
for x in my_numbers_list :
print GetNthPower(x)
# If I want 7th power then
GetNthPower.n = 7
This obviously will not work, is there any way to do this?
N.B: I know we can achieve this by setting 'n' as an argument of the function, but I want to do it this way for a particular reason.
I want my function to have only one argument (for using the function in multiprocessing.Pool.map()).
You can define static variables inside functions, almost like you did:
def GetNthPower(x) :
return x ** GetNthPower.n
GetNthPower.n = 3
print(GetNthPower(2)) #8
Make sure to initialize correctly your GetNthPower.n before first use though.
If you're worried about initialization, you could go for this version which uses a default value 1:
def GetNthPower(x) :
return x ** (GetNthPower.n if hasattr(GetNthPower, "n") else 1)
I think it would still be better for you to write a function that takes two arguments, or use the predefined ** operator.
Don't use one function; create a function that makes your function, using a closure.
def nth_power_maker(n):
def _(x):
return x ** n
return _
my_numbers_list = [11,23,45,56,78,98]
# now if I feel like I need the 4th power of some numbers in the list
get_4th_power = nth_power_maker(4)
for x in my_numbers_list:
print(get_4th_power(x))
get_7th_power = nth_power_maker(7)
Alternatively, you could use functools.partial to bind a keyword argument to a function
from functools import partial
def get_nth_power(x, n):
return x ** n
get_third = partial(get_nth_power, n=3)
get_third(4)
64
x = 4
# in a loop
for pow in [2, 4, 6, 8]:
f = partial(get_nth_power, n=pow)
f(x)
import math
x = 4
firstFunc = (3 * x) -5
secFunc = 4 - math.pow(2, x)
print(firstFunc, secFunc)
def addFunc(x=4):
result = firstFunc + secFunc
print(result)
print(addFunc)
I'm doing math homework so I decided to add two of these functions by defining a function parameter as x = 4. But unfortunately I'm getting this output "function addFunc at 0x10fae4f28"
You need to call the function like so:
print(addFunc())
What you are seeing is where the function is stored in memory after the def statement has executed, since the function is an object
I'm learning Python right now and I am just trying to get to grips with all of the syntax options.
Currently, the only thing that I can't seem to google up is what to do if I for some reason want to define a function which contains multiple other defines.
While I understand what to do if there's only 1 define inside the the larger define (val = f()(3,4) returns 7 if you exclude the second def below), I don't know how to correctly use the function below.
If it's possible, what is the syntax for a def function with an arbitrary amount of defined functions within it?
Code:
def f():
def x(a,b):
return a + b
return x
def y(c,d):
return c + d
return y
val = f()(3,4)(5,6)
print(val)
I expected the above to return either (7,11) or 11. However, it returns 'int object is not callable'
When you write val = f()(3,4)(5,6), you want f to return a function that also returns a function; compare with the simpler multi-line call:
t1 = f()
t2 = t1(3,4)
val = t2(5,6)
The function f defines and returns also has to define and return a function that can be called with 2 arguments. So, as #jonrsharpe said, you need more nesting:
def f():
def x(a, b):
def y(c, d):
return c + d
return y
return x
Now, f() produces the function named x, and f()(3,4) produces the function named y (ignoring its arguments 3 and 4 in the process), and f()(3,4)(5,6) evaluates (ultimately) to 5 + 6.