How do I manipulate functions to take new arguments? - python

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

Related

How to create a function that applies a function to the inputs of another function in Python?

I'm looking for a nice functional way to do the following:
def add(x, y):
return x + y
def neg(x):
return -x
def c(x, y):
# Apply neg to inputs for add
_x = neg(x)
_y = neg(y)
return add(_x, _y)
neg_sum = c(2, 2) # -4
It seems related to currying, but all of the examples I can find use functions that only have one input variable. I would like something that looks like this:
def add(x, y):
return x + y
def neg(x):
return -x
c = apply(neg, add)
neg_sum = c(2, 2) # -4
This is a fairly direct way to do it:
def add(x, y):
return x + y
def neg(x):
return -x
def apply(g, f):
# h is a function that returns
# f(g(arg1), g(arg2), ...)
def h(*args):
return f(*map(g, args))
return h
# or this:
# def apply(g, f):
# return lambda *args: f(*map(g, args))
c = apply(neg, add)
neg_sum = c(2, 2) # -4
Note that when you use *myvar as an argument in a function definition, myvar becomes a list of all non-keyword arguments that are received. And if you call a function with *expression as an argument, then all the items in expression are unpacked and sent as separate arguments to the function. I use these two behaviors to make h accept an unknown list of arguments, then apply function g to each one (with map), then pass all of them as arguments to f.
A different approach, depending on how extensible you need this to be, is to create an object which implements your operator methods, which each return the same object, allowing you to chain operators together in arbitrary orders.
If you can cope with it always returning a list, you might be able to make it work.
class mathifier:
def __init__(self,values):
self.values = values
def neg(self):
self.values = [-value for value in self.values]
return self
def add(self):
self.values = [sum(self.values)]
return self
print (mathifier([2,3]).neg().add().values)
And you can still get your named function for any set of chained functions:
neg_add = lambda x : mathifier(x).neg().add()
print(neg_add([2,3]).values)
From Matthias Fripp's answer, I asked myself : I'd like to compose add and neg both ways : add_neg(*args) and neg_add(*args). This requires hacking Matthias suggestion a bit. The idea is to get some hint on the arity (number of args) of the functions to compose. This information is obtained with a bit of introspection, thanks to inspect module. With this in mind, we adapt the way args are passed through the chain of funcs. The main assumption here is that we deal with real functions, in the mathematical sense, i.e. functions returning ONE float, and taking at least one argument.
from functools import reduce
from inspect import getfullargspec
def arity_one(func):
spec = getfullargspec(func)
return len(spec[0])==1 and spec[1] is None
def add(*args):
return reduce(lambda x,y:x+y, args, 0)
def neg(x):
return -x
def compose(fun1,fun2):
def comp(*args):
if arity_one(fun2): return fun1(*(map( fun2, args)))
else: return fun1(fun2(*args))
return comp
neg_add = compose(neg, add)
add_neg = compose(add, neg)
print(f"-2+(-3) = {add_neg(2, 3)}")
print(f"-(2+3) = {neg_add(2, 3)}")
The solution is still very adhoc...

Unable to understand Python nested function

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))

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 use creating polynomial expression like function in Python?

I'd like to write a program in Python where user define a deegre of polynomial and coefficients (a,b,c). When program create a polynomial expression with this data I'd like to use it like function because I need this to other operations. How can i get it? For example when I have polynomial= x^n+a^n-1+b^n-2+c^-3 I'd like to use it in polynomial(x) to calculate value.
Now the creating polynomial method looks:
def polynomial(n,a,b,c):
return a*x**n+b*x**3-c*x
class Polynomial:
def __init__(self, coeficents, degrees=None):
if degrees = None:
self.degree = list(reversed(range(len(coeficents))))
else:
self.degree = degrees
self.coeficents = coeficents
def __call__(self, x):
print(self.coeficents)
print(self.degree)
return sum([self.coeficents[i]*x**self.degree[i] for i in range(len(self.coeficents))])
p = Polynomial([1,2,4],[10,2,0])
print(p(2))
This will compute the polynomial x^10 + 2x^2 + 4 at x = 2. It should be very clear how to use with your example.
The best strategy is not to pass in n, but you will need to pass in x. You should instead pass the coefficients in as a list. You don't need to pass in n as it is calculated from the length of the list.
def poly(coefs, x):
result=0
N=len(coefs)
n=0
while N-n>0:
result+=coefs[n]*(x**(N-n-1))
n+=1
return result
So if you want to calculate, for example x^2 + 3x -5 where x=5, you would use this line:
print(poly([1,3,-5], 5))

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