在python中添加具有相同运算符的lambda函数



我有一个相当长的方程,需要使用scipy.integrate.quad进行积分,我想知道是否有方法将lambda函数相互添加。我想的是像这个

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

我真正使用的方程比我在这里暗示的要复杂得多,所以为了可读性,将方程分解成更小、更易于管理的部分会很有用。

有没有办法处理lambda函数?或者可能是另一种方式,它甚至不需要lambda函数,但会给出相同的输出?

在Python中,通常只将lambda用于非常短、简单的函数,这些函数很容易放在创建它们的行中。(有些语言有其他意见。)

正如@DSM在评论中暗示的那样,lambdas本质上是在不值得命名的情况下创建函数的快捷方式。

如果你正在做更复杂的事情,或者如果你需要给代码一个名称以供以后引用,lambda表达式对你来说并不是一个快捷方式——相反,你还不如用一个普通的旧函数def

因此,不将lambda表达式分配给变量:

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

函数和lambda都是"可调用的",这意味着就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,将列表向下应用到单个值)。

但是,如果您的代码与大多数代码一样,那么只按名称相互调用的常规函数将是最容易编写和读取的。

没有内置的功能,但您可以很容易地实现它(当然会带来一些性能打击):

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

可以以类似的方式添加其他运算符。

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

作为一名函数式程序员,我建议将解决方案推广到一个应用组合子:

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中的大多数内容可能足以用于典型的数学组合,从而避免编写任何lambda。

在类似的方式中,您可能希望定义lift1,也可能定义lift3

最新更新