toolz.thread_first()和toolz.thread_last()的目的是什么?

时间:2016-12-21 08:52:27

标签: python functional-programming toolz

请参阅toolz.thread_first()toolz.thread_last()

在我看来,他们使代码严格恶化。考虑

x = f(x)
x = g(x)
x = h(x)

VS

x = thread_last(x,
                f,
                g,
                h)

第一个例子是

  1. 更易读,易懂,
  2. 不依赖于外部Python库,
  3. 更容易调试,因为多个语句都有自己的行,并且
  4. 更详细,但不是很大。
  5. 即使你想通过x传递一个具有x = thread_first(x, *funcs)的可变大小的函数列表,这也可以通过常规迭代来完成 - 这又是更详细的,但是,不管怎么说,这种情况并不常见。

    为什么有人想要使用thread_first()thread_last()?它对我来说基本上看起来非常糟糕。 原则上,实现一种通过函数管道参数列表的方法可以通过并行化实现加速 - 但在我看来并不像在这些实现中实际发生这种情况。

1 个答案:

答案 0 :(得分:2)

虽然这主要是基于意见,但有许多好处:

命名很难(或者他们说)thread_*pipe允许您跳过中间分配。无需发明数十个中间名称,甚至更糟糕的是生活在xyz个变量中。

专注于数据流和数据结构启用干净的声明式样式。代码的大部分可以表示为简单的数据结构,并使用标准数据结构方法进行转换。可以说,它使您的代码更容易理解:

thread_first(
  url, 
  requests.get,
  requests.models.Response.json,
  operator.itemgetter("result"))

并撰写/重用代码:

request_pipeline = [authorize, fetch, validate]
api_response = [render_json]
html_response = [render_html]

thread_first(request, *request_pipeline + api_response)
thread_first(request, *request_pipeline + html_response)

将焦点转移到引用透明度它自然地强制执行小的,引用透明的函数,并且作为副作用(双关语)使您的代码更容易调试。

它可以很好地处理延迟代码toolz.maptoolz.filter),这使得它可以用于数据处理,可能是无限的数据结构。

最后你必须记住,这些功能不是单独存在的。它们旨在与toolz的其他部分(尤其是函数组合和currying),内置模块(如operator)一起使用,并且与第三方工具(如multipledispatch一起玩得非常好) )。只有这样,他们才能充分发挥自己的力量。

然而 toolz中实现的许多想法在严格的函数式语言(Clojure和Elixir)中更为自然,正如您所提到的,对于Python开发人员来说可能并不自然。