Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1076690
  • 博文数量: 165
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1351
  • 用 户 组: 普通用户
  • 注册时间: 2016-03-11 14:13
个人简介

狂甩酷拽吊炸天

文章分类

全部博文(165)

文章存档

2024年(1)

2023年(1)

2022年(3)

2021年(4)

2020年(17)

2019年(37)

2018年(17)

2017年(35)

2016年(50)

分类: Python/Ruby

2017-05-03 12:16:29


pipe并不是内置的库,如果你安装了easy_install,直接可以安装它,否则你需要自己下载它:

之所以要介绍这个库,是因为它向我们展示了一种很有新意的使用迭代器和生成器的方式:流。pipe将可迭代的数据看成是流,类似于linux,pipe使用'|'传递数据流,并且定义了一系列的“流处理”函数用于接受并处理数据流,并最终再次输出数据流或者是将数据流归纳得到一个结果。我们来看一些例子。

第一个,非常简单的,使用add求和:

[python]
  1. >>> from pipe import *
  2. >>> range(5) | add
  3. 10

    求偶数和需要使用到where,作用类似于内建函数filter,过滤出符合条件的元素:

    [python]
    1. >>> range(5) | where(lambda x: x % 2 == 0) | add
    2. 6

      还记得我们定义的斐波那契数列生成器吗?求出数列中所有小于10000的偶数和需要用到take_while,与itertools的同名函数有类似的功能,截取元素直到条件不成立:

      def fibonacci():
      a=b=1
      yield a
      yield b
      while True:
      a, b = b, a+b
      yield b
      [python]

      1. >>> fib = fibonacci
      2. >>> fib() | where(lambda x: x % 2 == 0)
      3. ... | take_while(lambda x: x < 10000)
      4. ... | add
      5. 3382


        需要对元素应用某个函数可以使用select,作用类似于内建函数map;需要得到一个列表,可以使用as_list:

        [python]
        1. >>> fib() | select(lambda x: x ** 2) | take_while(lambda x: x < 100) | as_list
        2. [1, 1, 4, 9, 25, 64]


          pipe中还包括了更多的流处理函数。你甚至可以自己定义流处理函数,只需要定义一个生成器函数并加上修饰器Pipe。如下定义了一个获取元素直到索引不符合条件的流处理函数:

          [python]
          1. >>> @Pipe
          2. ... def take_while_idx(iterable, predicate):
          3. ... for idx, x in enumerate(iterable):
          4. ... if predicate(idx): yield x
          5. ... else: return
          6. ...

            使用这个流处理函数获取fib的前10个数字:

            [python]
            1. >>> fib() | take_while_idx(lambda x: x < 10) | as_list
            2. [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]


              更多的函数就不在这里介绍了,你可以查看pipe的源文件,总共600行不到的文件其中有300行是文档,文档中包含了大量的示例。

              pipe实现起来非常简单,使用Pipe装饰器,将普通的生成器函数(或者返回迭代器的函数)代理在一个实现了__ror__方法的普通类实例上即可,但是这种思路真的很有趣。

               

      一道面试题:

      读取文件,统计文件中每个单词出现的次数,然后按照次数高低排序。

       

      本来蛮平淡无奇的一题,但一跟刚刚介绍的 Pipe 结合起来,就有意思了,这类数据流的处理,相当适合用 Pipe 来处理,花了点时间,写代码如下:


       

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      #coding=utf-8
      from re import split
      from pipe import *
       
      with open(r'C:UsersAdministratorDesktop.py') as f: 
          print(f.read() 
              | Pipe(lambda x:split('W+', x)) 
              | Pipe(lambda x:(i for i in x if i.strip())) 
              | groupby(lambda x:x) 
              | select(lambda x:(x[0], (x[1] | count))) 
              | sort(key=lambda x:x[1], reverse=True) 
              )

      输出结果:

       

      [('request', 91), ('POST', 81), ('and', 38), ('u', 36), ('if', 33), ('in', 32), ('team', 29), ('line', 23), ('objects', 20), ('gcmgroups', 16), ('get', 14), ('import', 14), ('save', 13), ('str', 12), ('0', 11), ('1', 11), ('i', 11), ('False', 10), ('GcwGroups', 9), ('from', 9), ('group_name', 9), ('path', 9), ('team_groups', 9), ('add', 8), ('else', 8), ('extra_context', 8), ('form2', 8), ('return', 8), ('Area', 7), ('baoming', 7), ('cname', 7), ('cname1', 7), ('cname2', 7), ('form1', 7), ('_cur', 7), ('8', 6), ('gender', 6), ('is_del', 6), ('time', 6), ('user', 6), ('20', 5), ('7', 5), ('def', 5), ('depth', 5), ('for', 5), ('gcwteam', 5), ('radio1', 5), ('13', 4), ('16', 4), ('2', 4), ('2013', 4), ('5', 4)]

阅读(2197) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~