关于功能:Python函数式编程

Python functional programming

我的问题是:

假设我们有3个函数:f、g、h和以下代码

1
2
3
y = f(x)
a = g(y)
b = h(y)

我想在一行上执行此操作,例如:

1
a,b = g(f(x)),h(f(x))

但是,如果f非常慢(并且不缓存结果),这是不有效的。

我有一个关于发电机的解决方案:

1
a,b = ((g(y),h(y)) for y in (f(x),)).next()

但这个不太可读

我想做这样的事情:

1
with  f(x) as y: a,b = g(y),h(y)

有人有主意吗?

(这是骗局)

1
y = f(x);a = g(y);b = h(y)

)

代码

1
2
3
4
5
6
7
8
9
10
11
12
import time
def f(t):
    time.sleep(1)
    print 'f called'
    return t

def g(t): return 1

def h(t): return 2

a,b = g(f(x)),h(f(x))
a,b = ((g(y),h(y)) for y in (f(x),)).next()


使用λ。塔达!:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
>>> def f(a):
...     return a+1
...
>>> def g(a):
...     return a*2
...
>>> def h(a):
...     return a*3
...
>>> (lambda x: (g(x),h(x)))(1)
(2, 3)
>>> (lambda x: (g(x),h(x)))(f(1))
(4, 6)
>>> a,b=(lambda x: (g(x),h(x)))(f(1))
>>> a
4
>>> b
6


我可能错过了这一点,但我认为没有什么问题

1
y = f(x); a,b = (g(y), h(y))

如果您经常在代码中执行此操作,并且所追求的是简单性,那么您可能可以创建一个实用函数,将参数映射到一系列函数:

1
2
3
def xmap(v, f_iter):
   "Subjects v to every function in f_iter and returns a list of results"
    return [f(v) for f in f_iter]

然后你可以做:

1
a, b = xmap(f(x), [g, h])

map的习惯用法是众所周知的,因此这种方法可以说是可读的,也可以理解,即xmap()类似于map(),但是args和funcs被转换了。


如果你想使用with语句,你可以用contextlib.contextmanager修饰f()并从中屈服:

1
2
3
4
5
6
7
8
9
10
from contextlib import contextmanager

@contextmanager
def f(t):
    time.sleep(1)
    print 'f called'
    yield t

with f(1) as y:
    a, b = g(y), h(y)