Unable to understand Python nested function - python

Im trying to figure out ,how this code works without calling the function (num2)?
Example:
def num1(x):
def num2(y):
return x * y
return num2
res = num1(10)
print(res(5))
Output:
50

It does call num2. That's what gets assigned to res, so res(5) calls it.
It might be slightly clearer if you rewrite num1 to use a lambda expression (which is possible due to the simple nature of the function being defined and returned):
def num1(x):
return lambda y: x * y
res = num1(10) # res is a function that multiplies its argument by 10
print(res(5))

If you try to print res without giving any argument in it, you can see it behaves like a function shortly points a function address ;
def num1(x):
def num2(y):
return x * y
return num2
res = num1(10)
print(res)
print(res(5))
Output;
<function num1.<locals>.num2 at 0x02DDBE38>
50

I commented this to explain the functions.
# Defined function named num1 taking input 'x'
def num1(x):
# Function 'num2' defined inside 'num1' taking input 'y'
def num2(y):
# Second function returning num1 input * num2 input
return x * y
# First function returning num2 is returned first
return num2
# this is a variable for inputting to the nested functions.
# res = num1(num2)
res = num1(10)
# This is initializing num1 as 5
print(res(5))
# But it would be way easier...
def nums(x,y):
return x * y
print(nums(5,10))

Related

How to create functions in python such that they return x as a variable? (interpolation)

How to create a functinon in Python such that for example:
n = int(input("number of knots: "))
xsolmed=[]
for i in range(n+1):
xsolmed.append(-1+(2*i/n))
def x(x):
return x
lni=[]
formula=1
for i in range(n+1):
for j in range(n+1):
if i==j:
pass
formula = (x(x)-xsolmed[i])/(xsolmed[j]-xsolmed[i])*formula
I think I need it to return the function such that the formula variable is a function by x in its own right and so later i can call upon it in the fashion
formula(10)=output
Set the results of a function call equal to your desired variable.
def f(x):
"A function that changes nothing"
return x
a = f(5) # same as a = 5
To avoid confusion, I recommend that you don't give functions the same name as their arguments, (i.e., don't do def x(x): ...).
If you want formula to be a function, then declare it as one, after which the correct syntax would be output = formula(10).
formula(10) is instance of a function and hence only has a value not a variable name to assign to.
A good way to write above code will be:
n = int(input("number of knots: "))
xsolmed=[]
for i in range(n+1):
xsolmed.append(-1+(2*i/n))
def y(x):
return x
def formula_calc(X):
formula=1
for i in range(n+1):
for j in range(n+1):
if i==j:
pass
formula = (X-xsolmed[i])/(xsolmed[j]-xsolmed[i])*formula
return formula
# now formula is a function of x. X can itself be a function.
print(formula(y(7))
# this will print value of formula at 7 as x(7) is 7.

Defining a function that returns another function as an output

I am trying to define a function f() that will use a function g() n times - f(g(x), n) - to modify a single input. The thing is, I want to make it so that f(g(x), n) will output another function k(), such that k(a) will give me the final result. For example:
square = lambda x : x*x
test = f(square, 2)
test(2) = (2^2)^2 = 16
I have had many attempts, but most of the time a TypeError would occur.
Here is one of my attempts:
def square(x):
return x*x
def mainfunc(function, no_of_times):
def func(x):
if no_of_times == 0:
return x
else:
return function(mainfunc(function, no_of_times - 1))
return func
test = mainfunc(square, 2)
print(test(2))
Can I have some advice on whether I have had the correct approach? If not, what should I do?
Let's assume function and no_of_times are just global names. A function that applies function no_of_times times to a given value is easy to implement:
def func(x):
for _ in range(no_of_times):
x = function(x)
return x
But you want a function f that returns such a function. And also, function and no_of_times shall be parameters of f, not global variables. So simply wrap the func definition in the function f with the wanted signature and return the resulting inner function:
def f(function, no_of_times):
def func(x):
for _ in range(no_of_times):
x = function(x)
return x
return func
This works as wanted:
>>> f(lambda x: x*x, 2)(2)
16
>>> g = lambda x: x*x
>>> k = f(g, 2)
>>> k(2)
16
>>> g = lambda x: f'g({x})'
>>> k = f(g, 5)
>>> k('spam')
'g(g(g(g(g(spam)))))'
Implementing the inner function func in a functional style is left as an exercise to the reader. (And also wasn't what the question asked for.)
A few issues with your code:
You need to return 1 when you want to run the function zero times.
In the recursive part of mainfunc you use function(mainfunc(function, no_of_times - 1)). The use of the outer function is incorrect as you are calling your square function with a function object as its argument when it expects an int.That is why you get a TypeError: unsupported operand type(s) for *: 'function' and 'function'.
In the recursive part of the function you need square(x) * mainfunc(function, no_of_times - 1)(x).
Two points to note regarding point 3:
Your mainfunc returns func which expects an int as its argument. Thus, when you recurse you need to call it as follows: mainfunc(function, no_of_times - 1)(x).
Since you are now recursing no_of_times -1 you need to multiply by function(x) to ensure that your recursive function works as intended.
def square(x):
return x * x
def mainfunc(function, no_of_times):
def func(x):
if no_of_times == 0:
return 1
else:
return function(x) * mainfunc(function, no_of_times - 1)(x)
return func
test = mainfunc(square, 3)
print(test(3))
Output: 64

How do I manipulate functions to take new arguments?

I was wondering how I could manipulate a function to take a new argument in Python without modifying original formula.
For example, how would I take square function and make another function like multiply square using square function as a model:
Original Function:
def square(x):
result = (x*x)
return(result)
New Function, takes a new argument "y":
def multSquare(x,y):
result = y*square(x)
return(result)
I tried using decorators but I can't seem to have it working
def addArg(tarFun):
def wrapArg(y, *args, **kwargs):
result=tarFun(*args, **kwargs) * y
return result
return wrapArg
def square(x):
result = (x*x)
return(result)
multSquare = addArg(square)
print(square(2)) # This should be 4
print(multSquare(2,3)) # This should be 12
This doesn't work because I don't how to inject y.
In the end, I want to make a function that takes all the arguments of the original function plus one more argument.
Thanks everybody!
If you pay attention to the order of your arguments, what's happening is that you are squaring 3 and multiplying it by 2. This is because your function wrapArg uses the first argument (2) as the number you are multiplying with and the second (3) as the number you are squaring.
multSquare(3, 2) will give the result you want.
In additional to what busybear said you could just swap the parameters around
def addArg(fun):
def wrapArg(x, y):
result = fun(x) * y
return result
return wrapArg
def square(x):
result = (x * x)
return(result)
multSquare = addArg(square)
print(square(2)) # This should be 4
print(multSquare(2, 3)) # This should be 12
or additionally just use optional arguments
def square(x, y = None):
sq = x*x
if y:
sq *= y
return sq

How do you read a lambda function as a string?

I'd like to read a lambda function I created as a string, after I created it.
For example,
func = lambda num1,num2: num1 + num2
I'd like to read func as:
'lambda num1,num2: num1 + num2'
Is there a way to accomplish this or even read any part of the lambda function?
Edit: Changed my first answer as I misunderstood the question. This answer is borrowed from a number of other uses, however I have completed the code to only display the part of the string that you want.
import inspect
func = lambda num1,num2: num1 + num2
funcString = str(inspect.getsourcelines(func)[0])
funcString = funcString.strip("['\\n']").split(" = ")[1]
print funcString
Outputs the following string:
lambda num1,num2: num1 + num2
You can use getsourcelines from the inspect module to do this
This function returns as a list all of the lines of the definition of any function, module, class or method as well as the line number at which it was defined.
For example:
import inspect
f = lambda x, y : x + y
print inspect.getsourcelines(f)[0][0]
Will output the definition of the function as:
f = lambda x, y: x + y
You can use Python's eval() function:
>>> func = eval('lambda num1,num2: num1 + num2')
>>> func
<function <lambda> at 0x7fe87b74b668>
To evaluate any expression and return the value.
You can use Python's inspect module to get the desired code as a list of strings:
#!/usr/bin/env python3
# coding: utf-8
import inspect
func = lambda num1, num2: num1 + num2
def f():
a = 1
b = 2
return a + b
def get_code_as_string(passed_func):
return inspect.getsourcelines(passed_func)
if __name__ == '__main__':
# feed a lambda function
print(get_code_as_string(func))
#feed a normal function
print(get_code_as_string(f))
The output is as follows:
(['func = lambda num1, num2: num1 + num2\n'], 6)
(['def f():\n', ' a = 1\n', ' b = 2\n', ' return a + b\n'], 8)
As you can see inspect.getsourcelines() returns a tuple of a list and an integer. The list contains all the lines of the function passed to inspect.getsourcelines() and the integer represents the line number in which the provided functions starts.

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

Categories