Clojure有一个“ - >” macro,以递归方式插入每个表达式作为下一个表达式的第一个参数。
这意味着我可以写:
(-> arg f1 f2 f3)
它的行为类似于(shell管道):
f3(f2(f1(arg)))
我想在Python中这样做;然而,搜索似乎是一场噩梦!我无法搜索“ - >”,也无法搜索Python函数线程!
有没有办法超载,比如说,|运算符,以便我可以用Python写这个?
arg | f1 | f2 | f3
谢谢!
答案 0 :(得分:18)
或者可以通过以下方式使用reduce函数:
reduce(lambda x,f : f(x), [f1,f2,f3], arg)
答案 1 :(得分:14)
你可以自己轻松实现这样的事情。
def compose(current_value, *args):
for func in args:
current_value = func(current_value)
return current_value
def double(n):
return 2*n
print compose(5, double, double) # prints 20
答案 2 :(得分:9)
或试试http://dev-tricks.net/pipe-infix-syntax-for-python 提供如下语法的模块:
fib() | take_while(lambda x: x < 1000000)
| where(lambda x: x % 2)
| select(lambda x: x * x)
| sum()
答案 3 :(得分:8)
以霍华德的解决方案为基础:
def T(*args):
return reduce(lambda l, r: r(l), args)
def dbl(n):
return 2*n
T(5,dbl,dbl)
#=> 20
T(5,dbl,dbl,lambda x: 3*x)
#=> 60
答案 4 :(得分:3)
虽然我同情创建酷炫的新语言结构(Lisp宏)的愿望,但实际上并不是Python哲学:
>>> import this
[...]
There should be one-- and preferably only one --obvious way to do it.
但正如受访者所说,你可以通过各种方式进行功能链接。如果适合你的想法,这可能是更明确的类似Lisp的那个:
a = lambda x: x*2
b = lambda x: x+1
def chain(first, *args):
if len(args) == 0:
return first
else:
return first(chain(*args))
print chain(b, a, 1)
答案 5 :(得分:1)
pytoolz库中有一个thread function(实际上有两个;它们在多个参数的函数上略有不同)。
还有一个名为cytoolz的pytoolz库的cython实现,它可能更有效。它可以使用pip
安装。
答案 6 :(得分:1)
参加派对有点晚了,但这里有一个更干净的方法,imo。适合大多数FP需求。
def stream(*args):
return reduce(lambda a, t: t[0](t[1], a), args[1:], args[0])
基本地图,过滤,缩小:
>>> my_list = [1, 2, 3, 4, 5]
>>> stream(my_list,
... (map, lambda x: x ** 2),
... (filter, lambda x: x < 20),
... (reduce, lambda a, x: a + x))
30
答案 7 :(得分:1)
我相信一个非常“Pythonic”的方法是线程化这样的函数:
thread_functions(my_arg)(func1, func2, ...)
或者,如果您有多个初始参数:
thread_functions(arg1, arg2, ...)(func1, func2, ...)
要实现上述内容,可以这样做:
def thread_functions(*init_args):
def execute_functions(*functions_list):
x = functions_list[0](*init_args)
for func in functions_list[1:]:
try:
x = func(*x)
except TypeError:
x = func(x)
return x
return execute_functions
函数 thread_functions
接收初始参数集(可以是多个)并返回函数 execute_functions
。调用时,execute_functions
接收一组要迭代的函数,将前一次迭代的结果应用为当前函数的参数。它还处理可迭代和不可迭代的参数。
在 this GitHub Gist 中,我留下了一些其他解释并实现了一些示例以更好地演示用例。
答案 8 :(得分:-2)
不,没有(至少是理智的)。你也不想。为什么不写f3(f2(f1(arg)))
?或者更好的是,以不需要递归的方式对问题进行建模。
你可以通过在一个类中包装表达式并在该类中定义|
来重载__or__
,但是,为了对Guido的爱,请不要这样做。
您也可以执行btilly
所写的内容,但我也不建议这样做。在语言为您提供的内容中工作。