Подтвердить что ты не робот

Добавление лямбда-функций с одним и тем же оператором в python

У меня довольно длинное уравнение, которое мне нужно интегрировать с помощью scipy.integrate.quad, и мне было интересно, есть ли способ добавить лямбда-функции друг к другу. Что я имею в виду, это что-то вроде этого

y = lambda u: u**(-2) + 8
x = lambda u: numpy.exp(-u)
f = y + x
int = scipy.integrate.quad(f, 0, numpy.inf)

Уравнения, которые я действительно использую, гораздо сложнее, чем я здесь намекаю, поэтому для удобства чтения было бы полезно разбить уравнение на более мелкие и более управляемые части.

Есть ли способ работы с лямбда-функциями? Или, возможно, другой способ, который даже не требует лямбда-функций, но даст тот же результат?

4b9b3361

Ответ 1

В Python вы обычно используете только лямбда для очень коротких простых функций, которые легко помещаются внутри создаваемой строки. (Некоторые языки имеют другие мнения.)

Поскольку @DSM намекает на их комментарий, lambdas - это, по сути, ярлык для создания функций, когда не стоит давать им имя.

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

Поэтому вместо назначения выражения лямбда переменной:

y = lambda u: u**(-2) + 8

Вы можете определить эту переменную как функцию:

def y(u):
    return u**(-2) + 8

Что дает вам возможность немного объяснить или быть более сложным, или что вам нужно сделать:

def y(u):
    """
    Bloopinate the input

    u should be a positive integer for fastest results.
    """
    offset = 8
    bloop = u ** (-2)
    return bloop + offset

Функции и лямбды являются "вызываемыми", что означает, что они по существу взаимозаменяемы до scipy.integrate.quad().

Чтобы объединить вызовы, вы можете использовать несколько разных методов.

def triple(x):
   return x * 3

def square(x):
   return x * x

def triple_square(x):
   return triple(square(x))

def triple_plus_square(x):
    return triple(x) + square(x)

def triple_plus_square_with_explaining_variables(x):
    tripled = triple(x)
    squared = square(x)
    return tripled + squared

Есть более расширенные параметры, которые я бы рассмотрел, только если он сделает ваш код более четким (чего, вероятно, не будет). Например, вы можете поместить вызовы в список:

 all_the_things_i_want_to_do = [triple, square]

Как только они попадут в список, вы можете использовать операции над списками для работы над ними (в том числе применять их по очереди к reduce списку до одного значения).

Но если ваш код похож на большинство кодов, обычные функции, которые просто называют друг друга по имени, будут простейшими для записи и проще всего читать.

Ответ 2

Для этого нет встроенных функций, но вы можете реализовать его довольно легко (с некоторым успехом, конечно):

import numpy

class Lambda:

    def __init__(self, func):
        self._func = func

    def __add__(self, other):
        return Lambda(
            lambda *args, **kwds: self._func(*args, **kwds) + other._func(*args, **kwds))

    def __call__(self, *args, **kwds):
        return self._func(*args, **kwds)

y = Lambda(lambda u: u**(-2) + 8)
x = Lambda(lambda u: numpy.exp(-u))

print((x + y)(1))

Другие операторы могут быть добавлены аналогичным образом.

Ответ 3

С помощью sympy вы можете выполнять функциональную операцию следующим образом:

>>> import numpy
>>> from sympy.utilities.lambdify import lambdify, implemented_function
>>> from sympy.abc import u
>>> y = implemented_function('y', lambda u: u**(-2) + 8)
>>> x = implemented_function('x', lambda u: numpy.exp(-u))
>>> f = lambdify(u, y(u) + x(u))
>>> f(numpy.array([1,2,3]))
array([ 9.36787944,  8.13533528,  8.04978707])

Ответ 4

Используйте код ниже для получения того же результата с записью как меньше кода, насколько это возможно:

y = lambda u: u**(-2) + 8
x = lambda u: numpy.exp(-u)
f = lambda u, x=x, y=y: x(u) + y(u)
int = scipy.integrate.quad(f, 0, numpy.inf)

Ответ 5

Как функциональный программист, я предлагаю обобщить решения аппликативный комбинатор:

In [1]: def lift2(h, f, g): return lambda x: h(f(x), g(x))
In [2]: from operator import add
In [3]: from math import exp
In [4]: y = lambda u: u**(-2) + 8
In [5]: x = lambda u: exp(-u)
In [6]: f = lift2(add, y, x)
In [7]: [f(u) for u in range(1,5)]
Out[7]: [9.367879441171443, 8.385335283236612, 8.160898179478975, 8.080815638888733]

Используя lift2, вы можете комбинировать вывод двух функций с использованием произвольных двоичных функций беспроблемным способом. И большая часть материала в operator, вероятно, должна быть достаточной для типичных математических комбинаций, избегая необходимости писать любые лямбды.

В подобном fasion вы можете определить lift1 и, возможно, lift3 тоже.