函数式编程之pipeline——很酷有没有_djph26741的博客-程序员宅基地

技术标签: python  awk  shell  

Pipeline

pipeline 管道借鉴于Unix Shell的管道操作——把若干个命令串起来,前面命令的输出成为后面命令的输入,如此完成一个流式计算。(注:管道绝对是一个伟大的发明,他的设哲学就是KISS – 让每个功能就做一件事,并把这件事做到极致,软件或程序的拼装会变得更为简单和直观。这个设计理念影响非常深远,包括今天的Web Service,云计算,以及大数据的流式计算等等)

比如,我们如下的shell命令:

1
ps  auwwx |  awk  '{print $2}'  sort  -n |  xargs  echo

如果我们抽象成函数式的语言,就像下面这样:

1
xargs(  echo, sort(n, awk( 'print $2' , ps(auwwx)))  )

也可以类似下面这个样子:

1
pids  =  for_each(result, [ps_auwwx, awk_p2, sort_n, xargs_echo])

好了,让我们来看看函数式编程的Pipeline怎么玩?

我们先来看一个如下的程序,这个程序的process()有三个步骤:

1)找出偶数。
2)乘以3
3)转成字符串返回

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def  process(num):
     # filter out non-evens
     if  num  %  2  ! =  0 :
         return
     num  =  num  *  3
     num  =  'The Number: %s'  %  num
     return  num
 
nums  =  [ 1 2 3 4 5 6 7 8 9 10 ]
 
for  num  in  nums:
     print  process(num)
 
# 输出:
# None
# The Number: 6
# None
# The Number: 12
# None
# The Number: 18
# None
# The Number: 24
# None
# The Number: 30

我们可以看到,输出的并不够完美,另外,代码阅读上如果没有注释,你也会比较晕。下面,我们来看看函数式的pipeline(第一种方式)应该怎么写?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def  even_filter(nums):
     for  num  in  nums:
         if  num  %  2  = =  0 :
             yield  num
def  multiply_by_three(nums):
     for  num  in  nums:
         yield  num  *  3
def  convert_to_string(nums):
     for  num  in  nums:
         yield  'The Number: %s'  %  num
 
nums  =  [ 1 2 3 4 5 6 7 8 9 10 ]
pipeline  =  convert_to_string(multiply_by_three(even_filter(nums)))
for  num  in  pipeline:
     print  num
# 输出:
# The Number: 6
# The Number: 12
# The Number: 18
# The Number: 24
# The Number: 30

我们动用了Python的关键字 yield,这个关键字主要是返回一个Generator,yield 是一个类似 return 的关键字,只是这个函数返回的是个Generator-生成器。所谓生成器的意思是,yield返回的是一个可迭代的对象,并没有真正的执行函数。也就是说,只有其返回的迭代对象被真正迭代时,yield函数才会正真的运行,运行到yield语句时就会停住,然后等下一次的迭代。(这个是个比较诡异的关键字)这就是lazy evluation。

好了,根据前面的原则——“使用Map & Reduce,不要使用循环”,那我们用比较纯朴的Map & Reduce吧。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def  even_filter(nums):
     return  filter ( lambda  x: x % 2 = = 0 , nums)
 
def  multiply_by_three(nums):
     return  map ( lambda  x: x * 3 , nums)
 
def  convert_to_string(nums):
     return  map ( lambda  x:  'The Number: %s'  %  x,  nums)
 
nums  =  [ 1 2 3 4 5 6 7 8 9 10 ]
pipeline  =  convert_to_string(
                multiply_by_three(
                    even_filter(nums)
                )
             )
for  num  in  pipeline:
     print  num

但是他们的代码需要嵌套使用函数,这个有点不爽,如果我们能像下面这个样子就好了(第二种方式)。

1
2
3
pipeline_func(nums, [even_filter,
                      multiply_by_three,
                      convert_to_string])

那么,pipeline_func 实现如下:

1
2
3
4
def  pipeline_func(data, fns):
     return  reduce ( lambda  a, x: x(a),
                   fns,
                   data)

好了,在读过这么多的程序后,你可以回头看一下这篇文章的开头对函数式编程的描述,可能你就更有感觉了。

最后,我希望这篇浅显易懂的文章能让你感受到函数式编程的思想,就像OO编程,泛型编程,过程式编程一样,我们不用太纠结是不是我们的程序就是OO,就是functional的,我们重要的品味其中的味道

参考

补充:评论中redraiment这个评论大家也可以读一读。

感谢谢网友S142857 提供的shell风格的python pipeline:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class  Pipe( object ):
     def  __init__( self , func):
         self .func  =  func
 
     def  __ror__( self , other):
         def  generator():
             for  obj  in  other:
                 if  obj  is  not  None :
                     yield  self .func(obj)
         return  generator()
 
@Pipe
def  even_filter(num):
     return  num  if  num  %  2  = =  0  else  None
 
@Pipe
def  multiply_by_three(num):
     return  num * 3
 
@Pipe
def  convert_to_string(num):
     return  'The Number: %s'  %  num
 
@Pipe
def  echo(item):
     print  item
     return  item
 
def  force(sqs):
     for  item  in  sqs:  pass
 
nums  =  [ 1 2 3 4 5 6 7 8 9 10 ]
 
force(nums | even_filter | multiply_by_three | convert_to_string | echo)

转载于:https://www.cnblogs.com/bonelee/p/11235955.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/djph26741/article/details/101520644

智能推荐

[linux]用wpa_supplicant连接WIFI_engineer520的博客-程序员宅基地

连接WIFI创建配置文件# wpa_passphrase SSID passphrase > /etc/wpa_supplicant/wpa.conf如果隐藏了WIFI的SSID,则配置文件wpa.conf中需要有scan_ssid=1,如下所示network={ ssid="SSID" psk=4326154235432 scan_ssid=1}...

第10周项目2-用二叉树求解代数表达式_wangxiaojie6688的博客-程序员宅基地_计算代数表达式 (2.2) (10分)

问题及代码:/*Copyright (c)2016,烟台大学计算机与控制工程学院All rights reserved.文件名称:bigice.cbp作 者:王效杰完成日期:2016年11月2日版 本 号:v1.0问题描述:用二叉树来表示代数表达式,树的每一个分支节点代表一个运算符,每一个叶子节点代表一个运算数(为简化,只支持二目运算 的+、-、*、

从spring boot 到 spring cloud- 2018/7/17 (1)_神奇at的博客-程序员宅基地_spring cloud搭建2018

 学习spring cloud之前首先学习搭建spring boot框架 并且整合ssm框架,搭建一个demo使用eclipse 建立spring boot工程选择web 以及mybatiis/mysql工程结构如图所示建立models-》student.javapackage com.example.demo.models;public class Stude...

Hibernate框架详解(五)面向对象查询语言和锁_官小飞的博客-程序员宅基地_hibernate面向对象写法

Hibernate做了数据库中表和我们实体类的映射,使我们不必再编写sql语言了。但是有时候查询的特殊性,还是需要我们手动来写查询语句呢,Hibernate框架为了解决这个问题给我们提供了HQL(Hibernate  Query  Language)面向对象的查询语言,和QBC(Query by Criteria)完全面向对象的查询,这里简单总结一下如何是面向对象来编写ql语句呢。

华为手机广告“来自iPhone客户端”_西雅图IT圈的博客-程序员宅基地

西雅图IT圈:seattleit【今日作者】PowerBall选号机身体和灵魂总有一个要走在买PowerBall的路上女神Gal Gadot近日担任华为在美国的品牌大使,...

炬芯ATS2825爆发力惊人 创新Muvo 2c音效震撼_孟迎霞的博客-程序员宅基地

智能家居的如日中天为蓝牙找到了一席之地,原本沉寂多年的蓝牙技术,终于在智能交织的物联网时代再次崛起,作为无线协议的中坚技术,蓝牙标准被推向了爆发的风口。蓝牙市场的热度上涨,迅速催涨蓝牙终端产品层出不穷,包括蓝牙音箱、蓝牙耳机、蓝牙车载、智能蓝牙灯等产品琳琅满目,有关这类目的产品评测也逐渐占据各大媒体版面。 网上一位网友在对创新Muvo2c这款迷你型蓝牙音箱进行评测时,给予了较高评价,如...

随便推点

Dockerfile介绍 和 docker build常用命令介绍_小虚竹的博客-程序员宅基地_dockerfile build

1、什么是 dockerfile2、docker镜像制作的工作逻辑3、Dockerfile的基本结构4、Dockerfile格式 案例:5、Build镜像

GSEA-基因集富集分析_weixin_30512785的博客-程序员宅基地

1.为什么写?网上教程一抓一大把,有的能重复,有的不能重复不了,很多原因。别人能做的不代表你能复制,实践出真知。不做搬运工,只写有用的,防止以后忘记。每个人理解不同,记录下来,供自己今后参考,顺便分享他人。2.GSEA基本概念Gene Set Enrichment Analysis思路:使用预定义的基因集(通常来自功能注释或先前实验的结果),将基因按照在两类...

Java管道流_YANGQINZ的博客-程序员宅基地_管道流

1、管道流是用来在多个线程之间进行信息传递的Java流,被号称是难使用的流,被使用的频率比较低。它提供了多线程间信息传输的一种有效手段2、管道流包括四个类 PipedOutputStream/PipedWriter 和 PipedInputStream/PipedReader3、其中 PipedOutputStream/PipedWriter 是写入者/生产者/发送者;PipedInputSt...

西山居决赛_zucc_dianbei的博客-程序员宅基地

很刺激的比赛,虽然表现很捉鸡,但还是很开心。TC/CF规则,3小时,其中0.5小时是hack环节分数分布:1000-1000-1500-2000-200001:看了一下发现是道sb的拓扑排序(事实上不是),轻松过掉pretest02:分析错了最坏情况,以为暴力能过,然后就暴力了。。03:一开始就觉得是染色分成二分图然后最小割,但是不知道哪根筋搭错了又觉得不太对。。然后想了很久其

大数据 标准库 应用库_如何为您的应用选择合适的数据库_cxu0262的博客-程序员宅基地

大数据 标准库 应用库 选择“正确的”数据库通常对于应用程序的成功至关重要。 与考虑供应商的建议或因为已经碰巧已经拥有数据库而使用数据库相比,考虑数据存储的基本目的和需求很有用。 在选择数据库时,这些是最重要的问题: 您希望在应用程序成熟时存储多少数据? 您希望在高峰负载下同时处理多少个用户? 您的应用程序需要什么可用性,可伸缩性,延迟,吞吐量和数据一致性? 您的数据库架构...

创建Hull Shader_会头痛的可达鸭的博客-程序员宅基地_hull shader

一、前言 Hull Shader是舞台工作三个阶段的第一个阶段,可以实现tessellation, Hull Shader transforms将一组输入控制点 转化为 输出控制点,输入、输出点的数量根据转换内容和数量而变化二、设计Hull shader三、通过ID3D11Device::CreateHullShader创建hull-shader对象 HRESULT CreateHullShader( ...

推荐文章

热门文章

相关标签