Python 函数式编程
这是我的问题:
假设我们有三个函数:f、g、h,还有以下这段代码:
y = f(x)
a = g(y)
b = h(y)
我想把这个操作放在一行里,比如:
a,b = g(f(x)),h(f(x))
但如果f的运行很慢(而且它不缓存结果),这样做就不太高效了。
我有一个用生成器的解决方案:
a,b = ((g(y),h(y)) for y in (f(x),)).next()
但这个写法不太容易理解。
我想做成像这样的:
with f(x) as y: a,b = g(y),h(y)
有没有人有什么想法?
( 这有点作弊
y = f(x);a = g(y);b = h(y)
)
代码
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()
3 个回答
1
如果你想使用 with
语句,可以这么做,只需要在 f()
函数前加上 contextlib.contextmanager
的装饰器,然后在里面使用 yield:
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)
3
我可能没理解到重点,但我觉得这段代码没有什么问题:
y = f(x); a,b = (g(y), h(y))
如果你在代码中经常需要做这个操作,而且你想要简单一些,那你可以创建一个工具函数,这个函数可以把一个参数“映射”到一系列函数上:
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]
然后你可以这样做:
a, b = xmap(f(x), [g, h])
这个 map
的用法大家都很熟悉,所以这种方法可以说是比较易读和容易理解的,也就是说,xmap()
就像 map()
,只是参数和函数的位置换了。
6
使用一个lambda表达式。就是这么简单!:
>>> 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