是否有类似Python中Clojure的线程宏?

时间:2018-05-04 13:50:04

标签: python functional-programming

在Clojure中我可以这样做:

(-> path
      clojure.java.io/resource
      slurp
      read-string)

而不是这样做:

(read-string (slurp (clojure.java.io/resource path)))

这在Clojure术语中称为线程 ,有助于摆脱大量括号。

在Python中,如果我尝试使用像mapanyfilter这样的功能结构,我必须将它们相互嵌套。在Python中是否有一个构造,我可以在Clojure中做类似于线程化(或管道化)的操作?

我没有找到功能齐全的版本,因为Python中没有宏,我只是想在我用Python进行函数式编程时取消很多括号。

修改:我最终使用支持pipe的{​​{3}}。

2 个答案:

答案 0 :(得分:6)

这是@deceze的想法的简单实现(尽管,正如@Carcigenicate指出的那样,它最多只是一个部分解决方案):

import functools
def apply(x,f): return f(x)
def thread(*args):
    return functools.reduce(apply,args)

例如:

def f(x): return 2*x+1
def g(x): return x**2
thread(5,f,g) #evaluates to 121

答案 1 :(得分:1)

我想把它变为极端,并动态地完成所有工作。

基本上,下面的Chain类允许您将函数链接在一起,类似于Clojure的->->>宏。它支持线程化到第一个和最后一个参数。

按此顺序解决功能:

  1. 对象方法
  2. 本地定义的变量
  3. 内置变量
  4. 代码:

    class Chain(object):
        def __init__(self, value, index=0):
            self.value = value
            self.index = index
        def __getattr__(self, item):
            append_arg = True
            try:
                prop = getattr(self.value, item)
                append_arg = False
            except AttributeError:
                try:
                    prop = locals()[item]
                except KeyError:
                    prop = getattr(__builtins__, item)
            if callable(prop):
                def fn(*args, **kwargs):
                    orig = list(args)
                    if append_arg:
                        if self.index == -1:
                            orig.append(self.value)
                        else:
                            orig.insert(self.index, self.value)
                    return Chain(prop(*orig, **kwargs), index=self.index)
                return fn
            else:
                return Chain(prop, index=self.index)
    

    将每个结果作为第一个arg

    进行线程化
    file = Chain(__file__).open('r').readlines().value
    

    将每个结果作为最后一个arg

    result = Chain(range(0, 100), index=-1).map(lambda x: x * x).reduce(lambda x, y: x + y).value