当前位置: 首页 > 科技观察

使用Python的toolz库开始函数式编程

时间:2023-03-13 01:18:19 科技观察

toolz库允许您操作函数,使您的代码更容易理解和测试。在这个由两部分组成的系列的第二部分中,我们将继续探索如何将函数式编程方法中的好想法引入Python,以实现两全其美。在上一篇文章中,我们介绍了不可变数据结构。这些数据结构允许我们编写“纯”函数,或者没有副作用的函数,它们只接受一些参数并返回结果,同时保持良好的性能。在本文中,我们使用toolz库来构建。这个库有用于操作这些函数的函数,它们与纯函数一起工作得特别好。在函数式编程世界中,它们通常被称为“高阶函数”,因为它们将函数作为参数并返回函数作为结果。让我们从这里开始:defadd_one_word(words,word):returnwords.set(words.get(word,0)+1)这个函数假设它的第一个参数是一个不可变的类字典对象,它返回一个新的类字典对象在相关位置递增:这是一个简单的频率计数器。但是,只有将它应用于单词流并进行归纳时,它才有用。我们可以使用内置模块functools中的诱导器。functools.reduce(function,stream,initializer)我们想要一个应用于流的函数,它返回一个频率计数。我们首先使用toolz.curry函数:add_all_words=curry(functools.reduce,add_one_word)要使用这个版本,我们需要提供一个初始化器。但是,我们不能只将pyrsistent.m函数添加到curry函数中;因为顺序错了。add_all_words_flipped=flip(add_all_words)flip这个高阶函数返回一个函数,该函数调用原始函数并翻转参数。get_all_words=add_all_words_flipped(pyrsistent.m())我们使用flip来自动调整它的参数,并给它一个初始值:一个空字典。现在我们可以执行函数get_all_words(word_stream)来获取频率词典。但是我们如何获得单词流呢?Python文件按行流式传输。defto_words(lines):forlineinlines:yieldfromline.split()在单独测试每个函数之后,我们可以将它们组合在一起:words_from_file=toolz.compose(get_all_words,to_words)在这种情况下,组合起来很容易读取两个函数:首先将文件的行流应用于to_words,然后将get_all_words应用于to_words的结果。但它的字面意思与代码的作用恰恰相反。当我们开始认真对待可组合性时,这一点很重要。有时可以将代码编写为一系列单元,分别测试每个单元,最后将它们全部组合起来。当有多个组合元素时,组合顺序可能很难理解。toolz库借鉴了Unix命令行并使用pipe作为一个函数来做同样的事情,但顺序相反。words_from_file=toolz.pipe(to_words,get_all_words)现在读起来更直观:将输入通过管道传输到to_words,将结果通过管道传输到get_all_words。在命令行上,等效项如下所示:$catfiles|到_words|get_all_wordstoolz库允许我们操作函数、切片、划分和组合,使我们的代码更易于理解和测试。