Как добавить функции - PullRequest
       28

Как добавить функции

8 голосов
/ 04 ноября 2010

Я просмотрел все, но это трудная тема для поиска без большого шума. Я хочу сделать что-то вроде этого:

def f(arg):
  return arg * arg

def add(self, other):
  return self * other

f.__add__ = add

cubefunction = f + f

Но я получаю ошибки при назначении функции cube, например:

TypeError: unsupported operand type(s) for +: 'function' and 'function'

Нет ли в Python функциональной алгебры или я просто совершаю глупую ошибку?

edit: гораздо позже, я читал официальное введение Python в функциональное программирование (http://docs.python.org/howto/functional.html),, а внизу он ссылается на сторонний пакет "функционал" (http://oakwinter.com/code/functional/documentation/),, который может составлять функции, т.е. :

>>> from functional import compose
>>> def add(a, b):
...     return a + b
...
>>> def double(a):
...     return 2 * a
...
>>> compose(double, add)(5, 6)
22

Ответы [ 6 ]

6 голосов
/ 05 ноября 2010

Я не думаю, что вы можете сделать это. Однако использование магического метода __call__ позволяет вам определить свой собственный вызываемый класс, который действует как функция и для которого вы можете определять __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

Здесь + перегружен для точечного сложения и * для композиции. Конечно, вы можете делать все что угодно.


Интересный вопрос для гуру Python: почему следующее не работает (хотя это грязное хакерство)?

>>> 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'
1 голос
/ 06 мая 2016

Немного поздно, но этот тип алгебры можно легко сделать с помощью лямбда-функций:

>>> 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 и g не должны быть лямбда-функциями)

С этим можно делать всякие интересные вещи. Допустим, вы хотите определить функцию f(x) = 1 + x + x**2 + ... + x**n для данного n. Вы можете сделать:

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

Чтобы понять, почему я сделал лямбду таким образом (lambda x, j = i + 1, k = f:), лучше прочитать это: https://docs.python.org/3.5/faq/programming.html#why-do-lambdas-defined-in-a-loop-with-different-values-all-return-the-same-result

Короче говоря: параметры в лямбда-функции не имеют локальной копии. Если бы я использовал i из цикла, как в lambda x, k = f: k(x) + x**(i + 1), у нас была бы функция f(x) = 1 + x**3 + x**3 + x**3.

1 голос
/ 18 января 2013

Ну, я думаю, у меня есть кое-что интересное для добавления функций.Речь идет о лямбда-функции, и она может решить вашу проблему.По крайней мере это исправило мой:

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

и для тех, кому интересно передать параметры

>>> 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
1 голос
/ 05 ноября 2010

В вашем коде f должен быть классом, а не функцией.Если у вас есть класс, вы можете реализовать метод add (self, other), который перегрузит оператор +.

1 голос
/ 04 ноября 2010

Я думаю, что вы хотите сделать, это:

cubefunction = (lambda x: add(f(x), f(x)))
0 голосов
/ 05 ноября 2010

Шаг 1. Прочитайте это.http://en.wikipedia.org/wiki/Function_composition_(computer_science)#First-class_composition

Шаг 2. Прочитайте это.http://en.wikipedia.org/wiki/Haskell_(programming_language)

Шаг 3. Прочитайте это.http://en.wikipedia.org/wiki/Scheme_(programming_language)

Это не самое приятное место для Python.

...