2015-12-14 25 views
17

我有一个相当长的方程,我需要使用scipy.integrate.quad进行整合,并且想知道是否有方法将lambda函数相互添加。我想到的是这样的在Python中使用相同的运算符添加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函数的方式,但会给出相同的输出?

+3

我对'scipy.integrate.quad'不熟悉,但'f = lambda u:y(u)+ x(u)'是一种将两个函数加在一起的方法。 –

+5

另外:如果你打算立即给你的函数一个名字,为什么你要使用'lambda'? – DSM

+0

老实说,我使用lambda,因为我不知道任何其他选项与我非常有限的python经验,这就是为什么我加了最后一部分的问题。 – coffeepls

回答

17

在Python中,你”通常只使用lambda表示非常简短的函数,这些函数可以很容易地放入创建它们的行内。 (某些语言有其他意见。)

由于@ DSM在他们的评论中暗示,lambdas本质上是创建函数时的一种快捷方式,因为它不值得给它们起个名字。

如果您正在做更复杂的事情,或者如果您需要为代码提供一个名称供以后参考,那么lambda表达式对您而言并不是什么捷径 - 相反,您可能还需要def ine一个普通的旧功能。的

因此,而不是分配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 

函数和lambdas都是“callabl e“,这意味着就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

这可能是OP的真正问题的解决方案。 – justhalf

+0

这是pythonic和可测试的。 Lambda应该显然是正确的。如降低字符串或添加常量。对于大多数情况下的数字代码,最好是提取函数。它也不会像上面看到的那样鼓励单个名称变量。 – bearrito

11

有对于没有内置功能,但你可以很容易地实现(有一些性能损失,当然)它:

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

其他运营商可以以类似的方式来添加。下面

+0

这对创建一个完整的DSL很有用,但请注意,有很多复杂的小问题需要处理。你需要做一些非常彻底的边缘案例测试才能顺利进行。对于大多数应用程序来说,这可能是不值得的麻烦,这让RJHunter的解决方案留下了难题。尽管如此,用于重写操作符的Python方式的+1。 – jpmc26

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

随着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]) 
3

作为一个功能性的程序员,我建议推广的解决方案,以一个applicative combinator

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,你可以结合使用任意的二进制功能于一身的pointfree方式两个函数的输出。并且operator中的大部分内容对于典型的数学组合应该足够了,从而避免必须编写任何lambda表达式。

在一个类似的方法中,你可能想要定义lift1或者lift3

相关问题