简体   繁体   English

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

[英]What is the purpose of toolz.thread_first() and toolz.thread_last()?

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

It seems to me that they make code strictly worse off . 在我看来,它们使代码变得更加糟糕 Consider 考虑

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

vs.

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

The first example is 第一个例子是

  1. more readable and easily understood, 更易读易懂,
  2. not reliant on an external Python library, 不依赖外部Python库,
  3. easier to debug, as the multiple statements each have their own line, and 易于调试,因为多个语句都有自己的行,并且
  4. more verbose, but not by a significant margin. 更详细,但幅度不大。

Even if you wanted to pass x through, say, a variably-sized list of functions with x = thread_first(x, *funcs) , this could just be accomplished with regular iteration--which is, again, more verbose, but it's not like this situation comes up all that often anyway. 即使你想传递x通过,也就是说,与功能的可变大小的列表x = thread_first(x, *funcs) ,这可能仅仅是定期迭代完成-这是再次,更详细的,但它不是这样的情况总会经常出现。

Why would anyone want to use thread_first() and thread_last() ? 为什么有人要使用thread_first()thread_last() It basically seems like very bad style to me. 对我来说,这似乎基本上是很糟糕的风格。 In principle , implementing a way to pipe a list of arguments through functions could result in speedups via parallelization--but it doesn't seem to me as though this actually happens with these implementations. 原则上 ,实现一种通过函数通过管道传递参数列表的方法可以通过并行化来加快速度,但是在我看来,这似乎并没有发生在这些实现中。

While this is mostly opinion based there is a number of benefits: 虽然这主要是基于意见的,但有很多好处:

Naming things is hard (or so they say) thread_* or pipe allows you to skip intermediate assignments. 命名很困难 (或如此thread_*thread_*pipe允许您跳过中间分配。 No need to invent dozens of intermediate names, or even worse living in a hell of x , y , z variables. 无需发明数十个中间名称,甚至不需要生活在xyz变量的地狱中。

Focus on data flow and data structures enables clean declarative style. 专注于数据流和数据结构可实现简洁的声明式样式。 Large parts of your code can be represented as simple data structures and transformed using standard data structure methods. 您的代码的大部分可以表示为简单的数据结构,并可以使用标准数据结构方法进行转换。 Arguably it makes your code easier to understand: 可以说它使您的代码更容易理解:

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

and compose / reuse code: 并编写/重用代码:

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)

Shift focus to referential transparency It naturally enforces small, referentially transparent functions and as a side effect (pun intended) makes your code much easier to debug. 将焦点转移到引用透明性自然地,它会强制执行较小的,引用透明性的功能,并且副作用(双关语)使您的代码更易于调试。

It plays very well with lazy code ( toolz.map , toolz.filter ) which makes it great for data processing on, possibly infinite, data structures. 它与惰性代码toolz.maptoolz.filter一起使用非常好,这使其非常适合在可能为无限数据结构上的数据处理。

Finally you have to remember that these functions don't exist alone . 最后,您必须记住,这些功能并不单独存在 They are intended to be used with other parts of toolz (especially function composition and currying), built-in modules (like operator ) and play really nice with 3rd party tools (like multipledispatch ). 他们的目的是与其他部分使用toolz (尤其是功能成分和柯里化),内置模块(如operator ),并发挥真的很好用第三方工具(如multipledispatch )。 Only then they show its full power. 只有这样,他们才能发挥出全部力量。

However many ideas implemented in toolz come are far more natural in strictly functional languages (Clojure and Elixir) and as you mentioned, may not feel natural for Python developers. 然而,在严格的功能语言(Clojure和Elixir)中,用toolz实现的许多想法要自然得多,而且正如您提到的那样,对于Python开发人员来说可能并不自然。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM