How to add functions
I have looked all over but it is a hard topic to search for without lots of noise. I want to 开发者_如何学运维do something like this:
def f(arg):
return arg * arg
def add(self, other):
return self * other
f.__add__ = add
cubefunction = f + f
But I get errors on the assignment to cubefunction like:
TypeError: unsupported operand type(s) for +: 'function' and 'function'
Is there no function algebra possible in python or am I just making a dumb mistake?
edit: much later, I was reading Python's official intro to functional programming (http://docs.python.org/howto/functional.html), and towards the bottom it references a third party package "functional" (http://oakwinter.com/code/functional/documentation/), which can compose functions, ie:
>>> from functional import compose
>>> def add(a, b):
... return a + b
...
>>> def double(a):
... return 2 * a
...
>>> compose(double, add)(5, 6)
22
I don't think you can do this. However, using the __call__
magic method lets you define your own callable class which acts as a function and upon which you can define __add__
:
>>> class FunctionalFunction(object):
... def __init__(self, func):
... self.func = func
...
... def __call__(self, *args, **kwargs):
... return self.func(*args, **kwargs)
...
... def __add__(self, other):
... def summed(*args, **kwargs):
... return self(*args, **kwargs) + other(*args, **kwargs)
... return summed
...
... def __mul__(self, other):
... def composed(*args, **kwargs):
... return self(other(*args, **kwargs))
... return composed
...
>>> triple = FunctionalFunction(lambda x: 3 * x)
>>> times_six = triple + triple
>>> times_six(2)
12
>>> times_nine = triple * triple
>>> times_nine(3)
27
Here +
is overloaded to pointwise addition, and *
to composition. Of course, you can do anything you like.
Interesting question for the Python gurus: why does the following not work (filthy hack though it is)?
>>> from types import MethodType, FunctionType
>>> f = lambda: None
>>> f.__add__ = MethodType(lambda self, other: "summed!", f, FunctionType)
>>> f.__add__(f)
'summed!'
>>> f + f
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'function' and 'function'
I think what you mean to do is:
cubefunction = (lambda x: add(f(x), f(x)))
In your code, f needs to be a class, not a function. If you have a class, you can implement an add(self, other) method that will overload the + operator.
Well I think I got something interesting to add functions. It's about lambda function and it could fix your problem. At least it fixed mine :
>>> def func( x ) :
>>> return x
>>>
>>> f = lambda x : func( x )
>>> sum_of_f = [ f for i in range( 5 ) ]
>>> F = lambda x : sum( [ i( x ) for i in sum_of_f ] )
>>> F( 1 )
5
>>> F( 2 )
10
and for those who are interested to pass parameters
>>> def func( x, p ) :
>>> return x * p
>>>
>>> param = [ 0, 1, 2, 3, 4 ]
>>>
>>> f = lambda x, p : func( x, p )
>>> sum_of_f = [ f for i in range( 5 ) ]
>>> F_bis = lambda x : sum( [ sum_of_f[i]( x, param[i] ) for i in range( 5 ) ] )
>>> F_bis( 1 )
10
>>> F_bis( 2 )
20
A bit late, but this kind of algebra can be done easily using lambda functions:
>>> f = lambda x: x*x
>>> g = lambda x: x*x
>>> h = lambda x: f(g(x))
>>> h(2)
16
>>> j = lambda x: f(x) + g(x)
>>> j(2)
8
>>>
(f and g do not need to be lambda functions)
You can do all sorts of interesting things with this. Let's say you want to define the function f(x) = 1 + x + x**2 + ... + x**n
for a given n
. You can do:
>>> n = 3
>>> f = lambda x: 1
>>> for i in range(n):
... f = lambda x, j = i + 1, k = f: k(x) + x**j
...
>>> f(2)
15
to understand why I made the lambda that way (lambda x, j = i + 1, k = f:
) is better to read this: https://docs.python.org/3.5/faq/programming.html#why-do-lambdas-defined-in-a-loop-with-different-values-all-return-the-same-result
Long story short: the parameters in a lambda function do not have a local copy. If I had used the i
from the loop as in lambda x, k = f: k(x) + x**(i + 1)
, we would have had the function f(x) = 1 + x**3 + x**3 + x**3
.
精彩评论