加入收藏 | 设为首页 | 会员中心 | 我要投稿 晋中站长网 (https://www.0354zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 移动互联 > 评测 > 正文

手把手介绍函数式编程:从命令式重构到函数式

发布时间:2019-09-10 00:12:11 所属栏目:评测 来源:佚名
导读:本文是一篇手把手的函数式编程入门介绍,借助代码示例讲解细腻。但又不乏洞见,第一节中列举和点评了函数式种种让眼花缭乱的特质,给出了『理解函数式特质的指南针:函数式代码的核心特质就一条,无副作用』,相信这个指南针对于有积极学过挖过函数式的同

或者,如果我们愿意为了简洁而牺牲一些可读性,那么可以写成:

  1. print pipeline_each(bands, [call(lambda x: 'Canada', 'country'), 
  2.                             call(lambda x: x.replace('.', ''), 'name'), 
  3.                             call(str.title, 'name')]) 

call() 的实现代码:

  1. def assoc(_d, key, value): 
  2.     from copy import deepcopy 
  3.     d = deepcopy(_d) 
  4.     d[key] = value 
  5.     return d 
  6.  
  7. def call(fn, key): 
  8.     def apply_fn(record): 
  9.         return assoc(record, key, fn(record.get(key))) 
  10.     return apply_fn 

上面的实现中有不少内容要讲,让我们一点一点地来说明:

  1. call() 是一个高阶函数。高阶函数是指将函数作为参数,或返回函数。或者,就像 call(),输入和返回2者都是函数。
  2. apply_fn() 看起来与三个转换函数非常相似。输入一个记录(一个乐队), record[key] 是查找出值;再以值为参数调用 fn ,将调用结果赋值回记录的副本;最后返回副本。
  3. call() 不做任何实际的事。而是调用 apply_fn() 时完成需要做的事。在上面的示例的 pipeline_each() 中,一个 apply_fn() 实例会设置传入乐队的 'country' 成 'Canada' ;另一个实例则将传入乐队的名字转成大写。
  4. 当运行一个 apply_fn() 实例, fn 和 key 2个变量并没有在自己的作用域中,既不是 apply_fn() 的参数,也不是本地变量。但2者仍然可以访问。
    • 当定义一个函数时,会保存这个函数能闭包进来( close over )的变量引用:在这个函数外层作用域中定义的变量。这些变量可以在该函数内使用。
    • 当函数运行并且其代码引用变量时, Python 会在本地变量和参数中查找变量。如果没有找到,则会在保存的引用中查找闭包进来的变量。就在这里,会发现 fn 和 key 。
  5. 在 call() 代码中没有涉及乐队列表。这是因为 call() ,无论要处理的对象是什么,可以为任何程序生成管道函数。函数式编程的一大关注点就是构建通用的、可重用的和可组合的函数所组成的库。

完美!闭包( closure )、高阶函数以及变量作用域,在上面的几段代码中都涉及了。嗯,理解完了上面这些内容,是时候来个驴肉火烧打赏一下自己。 :sushi:

最后还差实现一段处理乐队的逻辑:删除除名字和国家之外的内容。 extract_name_and_country() 可以把这些信息提取出来:

  1. def extract_name_and_country(band): 
  2.     plucked_band = {} 
  3.     plucked_band['name'] = band['name'] 
  4.     plucked_band['country'] = band['country'] 
  5.     return plucked_band 
  6.  
  7. print pipeline_each(bands, [call(lambda x: 'Canada', 'country'), 
  8.                             call(lambda x: x.replace('.', ''), 'name'), 
  9.                             call(str.title, 'name'), 
  10.                             extract_name_and_country]) 
  11.  
  12. # => [{'name': 'Sunset Rubdown', 'country': 'Canada'}, 
  13. #     {'name': 'Women', 'country': 'Canada'}, 
  14. #     {'name': 'A Silver Mt Zion', 'country': 'Canada'}] 

extract_name_and_country() 本可以写成名为 pluck() 的通用函数。 pluck() 使用起来是这个样子:

【译注】作者这里用了虚拟语气『*本*可以』。

(编辑:晋中站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读