Clojure 风格的函数“线程”在Python中
Clojure 有一个“->”递归插入每个表达式作为下一个表达式的第一个参数的宏。
这意味着我可以写:
(-> arg f1 f2 f3)
它的行为类似于(shell 管道):
f3(f2(f1(arg)))
我想在 Python 中执行此操作;然而,搜索似乎是一场噩梦!我无法搜索“->”,也无法搜索 Python 函数线程!
有没有办法超载,比如说 |运算符以便我可以用 Python 编写这个?
arg | f1 | f2 | f3
谢谢!
Clojure has a "->" macro which inserts each expression recursively as the first argument of the next expression.
This means that I could write:
(-> arg f1 f2 f3)
and it behaves like (shell piping):
f3(f2(f1(arg)))
I would like to do this in Python; however, searching seems to be a nightmare! I couldn't search for "->", and neither could I search for Python function threading!
Is there a way to overload, say, the | operator so that I could write this in Python?
arg | f1 | f2 | f3
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
发布评论
评论(9)
您可以自己轻松地实现这样的事情。
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
或者尝试 https://mdk.fr/blog/pipe-infix-语法-for-python.html
提供如下语法的模块:
fib() | take_while(lambda x: x < 1000000)
| where(lambda x: x % 2)
| select(lambda x: x * x)
| sum()
虽然我同情创建很酷的新语言结构(类似于 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)
聚会有点晚了,但我认为这是一个更干净的方法。适合大多数 FP 需求。
def stream(*args):
return reduce(lambda a, t: t[0](t[1], a), args[1:], args[0])
一个基本的map、filter、reduce:
>>> 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
我相信一种相当“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
接收一组要迭代的函数,将上一次迭代的结果应用为当前函数的参数。它还处理可迭代和不可迭代的参数。
在这个 GitHub Gist 中,我留下了一些其他解释并实现了一些示例,以更好地演示用例。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
或者可以按以下方式使用reduce函数:
Or possibly use the reduce function in the following way: