У меня есть довольно длинное уравнение, которое мне нужно интегрировать, используя 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)
Уравнения, которые я действительно использую, намного сложнее, чем я намекаю здесь, поэтому для удобства чтения было бы полезно разбить уравнение на более мелкие, более управляемые части.
Есть ли способ сделать с лямбда-функциями? Или, возможно, другой способ, который даже не требует лямбда-функций, но даст тот же результат?
5 ответов
В Python вы обычно будете использовать лямбду только для очень коротких, простых функций, которые легко помещаются в строку, которая их создает. (Некоторые языки имеют другие мнения.)
Как намекнул @DSM в своем комментарии, лямбды - это, по сути, ярлык для создания функций, когда не стоит давать им имя.
Если вы делаете более сложные вещи или если вам нужно дать коду имя для дальнейшей ссылки, лямбда-выражение не будет для вас чем-то вроде ярлыка - вместо этого вы можете def
и простая старая функция.
Таким образом, вместо присвоения лямбда-выражения переменной:
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
списку до одного значения).
Но если ваш код подобен большинству кода, обычные функции, которые просто вызывают друг друга по имени, будут проще всего писать и легче читать.
С 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])
Используйте приведенный ниже код, чтобы получить тот же результат, написав как можно меньше кода :
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)
Для этого нет встроенных функций, но вы можете реализовать их довольно легко (конечно, с некоторой потерей производительности):
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))
Другие операторы могут быть добавлены аналогичным образом.
Как функциональный программист, я предлагаю обобщить решения для аппликативный комбинатор:
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
должно быть достаточно для типичных математических комбинаций, избегая необходимости писать лямбды.
Аналогичным образом вы можете определить lift1
и, возможно, lift3
тоже.
Похожие вопросы
Новые вопросы
python
Python - это многопарадигмальный, динамически типизированный, многоцелевой язык программирования. Он разработан для быстрого изучения, понимания и использования, а также для обеспечения чистого и единообразного синтаксиса. Обратите внимание, что Python 2 официально не поддерживается с 01.01.2020. Тем не менее, для вопросов о Python, связанных с версией, добавьте тег [python-2.7] или [python-3.x]. При использовании варианта Python (например, Jython, PyPy) или библиотеки (например, Pandas и NumPy) включите его в теги.