博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python 文本处理2
阅读量:6720 次
发布时间:2019-06-25

本文共 3416 字,大约阅读时间需要 11 分钟。

接上文,我们定义了判断某行是否file copy,或者file overwrite的两个函数,事实上我们如果使用

startswith函数代替slice,会更稳定。从函数式编程角度,我们给出下面几个表达式:
      isRegDBRoot = lambda line: line[:11]=='RegDB Root:'
      isRegDBKey = lambda line: line[:10]=='RegDB Key:'
      isRegDBVal = lambda line: line[:10]=='RegDB Val:'
有了这三个更加紧凑的函数,我们给出之前方法的函数式编程写法;
      lines = open(r'd:\python22\install.log').readlines()
      regroot_lines = filter(isRegDBRoot, lines)
如果,你想通过多个选择标准来选择相应的行,那么函数式的写法就会显得笨拙。
我们可以根据相似的思路写出一个给定要求对应的过滤函数如下:
 #*--------------- Find the RegDB lines ------------------#
      def isAnyRegDB(line):
          if   line[:11]=='RegDB Root:': return 1
          elif line[:10]=='RegDB Key:':  return 1
          elif line[:10]=='RegDB Val:':  return 1
          else:                          return 0
但是,如果需求变成了其他的组合呢?显然依据这个思路,我们必须为另外的组合写更多的组合,这种组合是爆炸性的增长的。。。另外的思路是通过嵌套过滤函数来达到:
 #*------------- Filter on two line predicates -----------#
      shortline = lambda line: len(line) < 25
      short_regvals = filter(shortline, filter(isRegDBVal, lines))
这样的思路写出的程序比较容易排错,该函数使用了两个已有的函数来生成新的程序。但是一个显而易见的问题是:这样的程序很难阅读。同样的问题也出现在map函数上。通常解决这样问题的方法是多增加一些循环和中间变量。。
根据函授式编程的思路,我们可以在不增加代码量的情况下解决上面描述的问题。
这里的关键点是:选择的生成一些高级别的组合函数:这里的高级别函数是指:那些接受函数作为输入,返回函数作为输出的函数。一级函数接受数据,返回数据。相对应的一个高级函数的输入和输出都是函数对象。这些函数对象将在未来被其他地方使用:高级函数的一个例子是;函数工厂,它返回一个或者一组函数对象。下面是一个加法函数工厂;
>>> def adder_factory(n):
      ...    return lambda m, n=n: m+n
      ...
      >>> add10 = adder_factory(10)
      >>> add10
      <function <lambda> at 0x00FB0020>
      >>> add10(4)
      14
      >>> add10(20)
      30
      >>> add5 = adder_factory(5)
      >>> add5(4)
      9
回到正题,我们提到用高级组合函数来解决前面提到的问题,这些高级函数通过接受一些函数,对这些函数对象进行操作从而合成其他的函数。下面是一个组合高级函数库:
#------------------- combinatorial.py -------------------#
      from operator import mul, add, truth
      apply_each = lambda fns, args=[]: map(apply, fns, [args]*len(fns))
      bools = lambda lst: map(truth, lst)
      bool_each = lambda fns, args=[]: bools(apply_each(fns, args))
      conjoin = lambda fns, args=[]: reduce(mul, bool_each(fns, args))
      all = lambda fns: lambda arg, fns=fns: conjoin(fns, (arg,))
      both = lambda f,g: all((f,g))
      all3 = lambda f,g,h: all((f,g,h))
      and_ = lambda f,g: lambda x, f=f, g=g: f(x) and g(x)
      disjoin = lambda fns, args=[]: reduce(add, bool_each(fns, args))
      some = lambda fns: lambda arg, fns=fns: disjoin(fns, (arg,))
      either = lambda f,g: some((f,g))
      anyof3 = lambda f,g,h: some((f,g,h))
      compose = lambda f,g: lambda x, f=f, g=g: f(g(x))
      compose3 = lambda f,g,h: lambda x, f=f, g=g, h=h: f(g(h(x)))
      ident = lambda x: x
这样通过使用这些高级组合函数:我们可以这样解决之前遇到的问题:
 #----- Some examples using higher-order functions -----#
      # Don't nest filters, just produce func that does both
      short_regvals = filter(both(shortline, isRegVal), lines)
      # Don't multiply ad hoc functions, just describe need
      regroot_lines = \
          filter(some([isRegDBRoot, isRegDBKey, isRegDBVal]), lines)
      # Don't nest transformations, make one combined transform
      capFlipNorm = compose3(upper, flip, normalize)
      cap_flip_norms = map(capFlipNorm, lines)
可以看出通过函数式编程方法,我们可以不仅获得更加精炼的代码,以及更好的可读性.
任何嵌套的filter 和map函数都可以通过高级组合函数进行化简,总的来说,函数式编程方法得到的代码量应该在常规方法代码量的一半。
这种高级组合函数的另外一个好处是;他们可以提供一整套的函数的布尔表达式。
  #*---------- Simple Boolean algebra of values ----------#
      satisfied = (this or that) and (foo or bar)
在文本处理环境下,这样的操作经常是一些predic函数的结果。如下:
  #*---------- Boolean algebra of return values ----------#
      satisfied = (thisP(s) or thatP(s)) and (fooP(s) or barP(s))
通过之前的高级组合函数,我们可以得到如下代码:
 #*------ Boolean algebra of composed functions ------#
      satisfiedP = both(either(thisP,thatP), either(fooP,barP))
精简如斯啊。
一些问题下次再翻译,睡了。

转载于:https://www.cnblogs.com/zhangsong/archive/2012/07/10/2585412.html

你可能感兴趣的文章
嵌入式C题
查看>>
maven学习笔记
查看>>
说说Java线程池
查看>>
Linux挂载命令mount用法及参数详解
查看>>
Nginx 动静分离
查看>>
MySQL如何实现数组功能
查看>>
Android第四十七期 - WheelView沉浸式菜单栏
查看>>
Spring Boot--模板从JSP到Freemarker的若干问题
查看>>
Java内存模型的探究
查看>>
CentOS6.5 从源码编译安装 GCC-4.9.1 全程实录《第二部分:编译,安装,测试》
查看>>
反查bash历史记录--用Enki学Linux系列(16)
查看>>
Stateful firewall
查看>>
Redis 常见的客户端工具
查看>>
Linux Svn 安装
查看>>
我的友情链接
查看>>
Tornado 多进程 & 异步
查看>>
Mysql left join,right join,inner join的效率比较
查看>>
SpringMVC的返回视图几种方式
查看>>
lvs+keepalived实现实时监控节点健康状态,并根据算法接管资源
查看>>
JavaScript之基础-12 JavaScript 错误处理
查看>>