了解 toolz 用例
understanding toolz use cases
我正在学习一些函数式编程并正在研究 toolz。 compose、pipe、thread_first 和 thread_last 之间的差异对我来说似乎非常微妙或根本不存在。这些功能的预期不同用例是什么?
compose
对比 thread_*
和 pipe
compose
本质上是一个function compostion(∘)。它的主要目标是将不同的功能组合成 可重用 块。应用程序的顺序与参数的顺序相反,因此 compose(f, g, h)(x)
是 f(g(h(x)))
(与 (f ∘ g)(x) 相同 f (g(x))).
thread_*
和 pipe
是关于使用可重用块来创建单个数据流。只能通过惰性操作延迟执行,但块是固定的。应用顺序与参数顺序相同,因此 pipe(x, f, g, h)
是 h(g(f(x)))
.
compose
对比 thread_*
.
compose
不允许附加参数,而 thread_*
允许。没有柯里化 compose
只能与一元函数一起使用。
相对于thread_
可以使用更高阶的函数,包括常用的高阶函数:
thread_last(
range(10),
(map, lambda x: x + 1),
(filter, lambda x: x % 2 == 0)
)
与 compose
相同,您需要柯里化:
pipe(
range(10),
lambda xs: map(lambda x: x + 1, xs),
lambda xs: filter(lambda x: x % 2 == 0, xs)
)
或
from toolz import curried
pipe(
range(10),
curried.map(lambda x: x + 1),
curried.filter(lambda x: x % 2 == 0)
)
thread_first
对比 thread_last
.
thread_first
将管道参数放在函数的第一个位置。
thread_last
将管道参数放在函数的最后位置。
例如
>>> from operator import pow
>>> thread_last(3, (pow, 2)) # pow(2, 3)
8
>>> thread_first(3, (pow, 2)) # pow(3, 2)
9
在实践中(忽略一些形式主义)这些函数通常是可以互换的,尤其是当与 functools.partial
/ toolz.curry
和一些 lambda
表达式结合使用时,但根据上下文,它是一个比另一个更方便。
例如,对于内置的高阶函数,如 map
或 functools.reduce
,thread_last
是一个自然的选择。如果你想在多个地方重用一段代码,使用 compose(h, g, f)
比添加函数包装器 def fgh(x) pipe(x, f, g, h)
更好。等等。
我正在学习一些函数式编程并正在研究 toolz。 compose、pipe、thread_first 和 thread_last 之间的差异对我来说似乎非常微妙或根本不存在。这些功能的预期不同用例是什么?
compose
对比thread_*
和pipe
compose
本质上是一个function compostion(∘)。它的主要目标是将不同的功能组合成 可重用 块。应用程序的顺序与参数的顺序相反,因此compose(f, g, h)(x)
是f(g(h(x)))
(与 (f ∘ g)(x) 相同 f (g(x))).thread_*
和pipe
是关于使用可重用块来创建单个数据流。只能通过惰性操作延迟执行,但块是固定的。应用顺序与参数顺序相同,因此pipe(x, f, g, h)
是h(g(f(x)))
.compose
对比thread_*
.compose
不允许附加参数,而thread_*
允许。没有柯里化compose
只能与一元函数一起使用。相对于
thread_
可以使用更高阶的函数,包括常用的高阶函数:thread_last( range(10), (map, lambda x: x + 1), (filter, lambda x: x % 2 == 0) )
与
compose
相同,您需要柯里化:pipe( range(10), lambda xs: map(lambda x: x + 1, xs), lambda xs: filter(lambda x: x % 2 == 0, xs) )
或
from toolz import curried pipe( range(10), curried.map(lambda x: x + 1), curried.filter(lambda x: x % 2 == 0) )
thread_first
对比thread_last
.thread_first
将管道参数放在函数的第一个位置。thread_last
将管道参数放在函数的最后位置。例如
>>> from operator import pow >>> thread_last(3, (pow, 2)) # pow(2, 3) 8 >>> thread_first(3, (pow, 2)) # pow(3, 2) 9
在实践中(忽略一些形式主义)这些函数通常是可以互换的,尤其是当与 functools.partial
/ toolz.curry
和一些 lambda
表达式结合使用时,但根据上下文,它是一个比另一个更方便。
例如,对于内置的高阶函数,如 map
或 functools.reduce
,thread_last
是一个自然的选择。如果你想在多个地方重用一段代码,使用 compose(h, g, f)
比添加函数包装器 def fgh(x) pipe(x, f, g, h)
更好。等等。