千锋教育-做有情怀、有良心、有品质的职业教育机构

领取全套视频

扫码关注千锋教育
领取学科全套视频

当前位置:首页  >  技术文章  >  正文

5分钟带你详解python函数式编程与闭包

时间:2021-02-03 09:31     来源:千锋教育 作者:小千

      对于开发者来说除了基础语法之外,一些比较常用的开发手段也是需要去学习和使用的,这里小千就来教大家如何去使用Python里面的函数式编程和闭包。

      函数式编程

      函数式编程这个概念我们可能或多或少都听说过,刚听说的时候不明觉厉,觉得这是一个非常黑科技的概念。但是实际上它的含义很朴实,但是延伸出来许多丰富的用法。

      在早期编程语言还不是很多的时候,我们会将语言分成高级语言与低级语言。比如汇编语言,就是低级语言,几乎什么封装也没有,做一个赋值运算还需要我们手动调用寄存器。而高级语言则从这些面向机器的指令当中抽身出来,转而面向过程或者是对象。也就是说我们写代码面向的是一段计算过程或者是一个计算机当中抽象出来的对象。如果你学过面向对象,你会发现和面向过程相比,面向对象的抽象程度更高了一些,做了更加完善的封装。

      在面向对象之后呢,我们还可以做什么封装和抽象呢?这就轮到了函数式编程。

      函数我们都了解,就是我们定义的一段程序,它的输入和输出都是确定的。我们把一段函数写好,它可以在任何地方进行调用。既然函数这么好用,那么能不能把函数也看成是一个变量进行返回和传参呢?

      OK,这个就是函数式编程最直观的特点。也就是说我们写的一段函数也可以作为变量,既可以用来赋值,还可以用来传递,并且还能进行返回。这样一来,大大方便了我们的编码,但是这并不是有利无害的,相反它带来许多问题,最直观的问题就是由于函数传入的参数还可以是另一个函数,这会导致函数的计算过程变得不可确定,许多超出我们预期的事情都有可能发生。

      所以函数式编程是有利有弊的,它的确简化了许多问题,但也产生了许多新的问题,我们在使用的过程当中需要谨慎。

      传入、返回函数

      在我们之前介绍filter、map、reduce以及自定义排序的时候,其实我们已经用到了函数式编程的概念了。

      比如在我们调用sorted进行排序的时候,如果我们传入的是一个对象数组,我们希望根据我们制定的字段排序,这个时候我们往往需要传入一个匿名函数,用来制定排序的字段。其实传入的匿名函数,其实就是函数式编程最直观的体现了:

1

      除此之外,我们还可以返回一个函数,比如我们来看一个例子:

2

      如果这个时候我们调用delay_sum传入一串数字,我们会得到什么?

      答案是一个函数,我们可以直接输出,从打印信息里看出这一点:

3

      我们想获得这个运算结果应该怎么办呢?也很简单,我们用一个变量去接收它,然后执行这个新的变量即可:

4

      这样做有一个好处是我们可以延迟计算,如果不使用函数式编程,那么我们需要在调用delay_sum这个函数的时候就计算出结果。如果这个运算量很小还好,如果这个运算量很大,就会造成开销。并且当我们计算出结果来之后,这个结果也许不是立即使用的,可能到很晚才会用到。既然如此,我们返回一个函数代替了运算,当后面真正需要用到的时候再执行结果,从而延迟了运算。这也是很多计算框架的常用思路,比如spark。

      闭包

      我们再来回顾一下我们刚才举的例子,在刚才的delay_sum函数当中,我们内部实现了一个sum函数,我们在这个函数当中调用了delay_sum函数传入的参数。这种对外部作用域的变量进行引用的内部函数就称为闭包。

      其实这个概念很形象,因为这个函数内部调用的数据对于调用方来说是封闭的,完全是一个黑盒,除非我们查看源码,否则我们是不知道它当中数据的来源的。除了不知道来源之外,更重要的是它引用的是外部函数的变量,既然是变量就说明是动态的。也就是说我们可以通过改变某些外部变量的值来改变闭包的运行效果

      这么说有点拗口,我们来看一个简单的例子。在Python当中有一个函数叫做math.pow其实就是计算次方的。比如我们要计算x的平方,那么我们应该这样写:

5

      但是如果我们当前场景下只需要计算平方,我们每次都要传入额外再传入一个2会显得非常麻烦,这个时候我们使用闭包,可以简化操作:

6

      通过闭包,我们把第二个变量给固定了,这样我们只需要使用pow2就可以实现原来math.pow(x, 2)的功能了。如果我们突然需求变更需要计算3次方或者是4次方,我们只需要修改mypow的传入参数即可,完全不需要修改代码。

      实际上这也是闭包最大的使用场景,我们可以通过闭包实现一些非常灵活的功能,以及通过配置修改一些功能等操作,而不再需要通过代码写死。要知道对于工业领域来说,线上的代码是不能随便变更的,尤其是客户端,比如apple store或者是安卓商店当中的软件包,只有用户手动更新才会拉取。如果出现问题了,几乎没有办法修改,只能等用户手动更新。所以常规操作就是使用一些类似闭包的灵活功能,通过修改配置的方式改变代码的逻辑。

      除此之外闭包还有一个用处是可以暂存变量或者是运行时的环境。

      举个例子,我们来看下面这段代码:

7

      这是没有使用闭包的函数,不管我们调用多少次,答案都是5,执行完x+=5之后的结果并不会被保存起来,当函数返回了,这个暂存的值也就被抛弃了。那如果我希望每次调用都是依据上次调用的结果,也就是说我们每次修改的操作都能保存起来,而不是丢弃呢?

      这个时候就需要使用闭包了:

8

      也就是说我们的x的值被存储起来了,每次修改都会累计,而不是丢弃。这里需要注意一点,我们用到了一个新的关键字叫做nonlocal,这是Python3当中独有的关键字,用来申明当前的变量x不是局部变量,这样Python解释器就会去全局变量当中去寻找这个x,这样就能关联上test方法当中传入的参数x。Python2官方已经不更新了,不推荐使用。

      由于在Python当中也是一切都是对象,如果我们把闭包外层的函数看成是一个类的话,其实闭包和类区别就不大了,我们甚至可以给闭包返回的函数关联函数,这样几乎就是一个对象了。来看一个例子:

9

      最后运算的结果是xiaohong,因为我们调用set_name改变了闭包外部的值。这样当然是可以的,但是一般情况下我们并不会用到它。和写一个class相比,通过闭包的方法运算速度会更快。原因比较隐蔽,是因为闭包当中没有self指针,从而节省了大量的变量的访问和运算,所以计算的速度要快上一些。但是闭包搞出来的伪对象是不能使用继承、派生等方法的,而且和正常的用法格格不入,所以我们知道有这样的方法就可以了,现实中并不会用到。

      学习Python,可以参考千锋Python培训班推出的Python开发学习路线,结合千锋Python培训机构名师精心录制的全套Python视频教程,可以让你对学习Python需要掌握的知识有个清晰的了解,并快速入门Python开发。千锋Python培训机构视频教程分为三个大块:Python基础视频教程、Python高级视频教程、Python高手晋级视频教程。视频讲解通俗易懂,入门Python开发仅用此套视频足矣。想要获取免费Python学习路线和学习资料可以添加我们的Python技术交流qq群:790693323  加群找群管理领取即可,Python相关技术问题也可以加群解决,等你来哦~~~~

相关文章

Python开课预告

  • 北京Python培训班 02.10 抢座
  • 上海Python培训班 02.17 抢座
  • 广州Python培训班 03.11 开班
  • 深圳Python培训班 02.17 抢座
  • 成都Python培训班 02.17 抢座
  • 杭州Python培训班 03.11 开班
  • 武汉Python培训班 02.17 抢座
  • 西安Python培训班 02.24 抢座
  • 北京总部地址:北京市海淀区宝盛北里西区28号中关村智诚科创大厦4层
    北京沙河校区:北京市昌平区沙阳路18号北京科技职业技术学院广场服务楼
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、Adobe认证、PMP认证、红帽RHCE认证
  • 深圳校区地址:深圳市宝安区宝安大道5010号西部硅谷B座A区6层A605/B座C区1层108
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、Adobe认证、PMP认证、红帽RHCE认证
  • 上海校区地址:上海市宝山区同济支路199号智慧七立方3号楼2-4层
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、Adobe认证、PMP认证、红帽RHCE认证
  • 广州校区地址:广州市白云区永平街永泰学山塘学山文化创意谷A1栋六楼
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、Adobe认证、PMP认证、红帽RHCE认证
  • 郑州二七区校区地址:郑州市二七区航海中路60号海为科技园C区10层
    郑州高新区校区地址:郑州市高新区金梭路与银杏路交叉口教育科技产业园南门D座4层
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、Adobe认证、PMP认证、红帽RHCE认证
  • 大连校区地址:辽宁省大连市高新园区爱贤街10号大连设计城A座901
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、Adobe认证、PMP认证、红帽RHCE认证
  • 武汉金融港校区地址:武汉市东新区光谷大道77号金融港B18栋三、四层
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、Adobe认证、PMP认证、红帽RHCE认证
  • 成都校区地址:成都市高新区肖家河沿街138号肖家河大厦三楼
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、Adobe认证、PMP认证、红帽RHCE认证
  • 西安校区地址:西安市雁塔区高新六路52号立人科技C座西区4楼
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、Adobe认证、PMP认证、红帽RHCE认证
  • 杭州旺田校区:浙江省杭州市上城区九堡镇旺田书画城A座4层
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、Adobe认证、PMP认证、红帽RHCE认证
  • 青岛校区地址:青岛市市北区龙城路31号卓越世纪中心4号楼5层
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、Adobe认证、PMP认证、红帽RHCE认证
  • 重庆校区地址:重庆市高新区科园一路2号大西洋国际12-1
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、Adobe认证、PMP认证、红帽RHCE认证
  • 长沙校区地址:湖南省长沙市岳麓区麓谷企业广场A2栋三单元306号
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、Adobe认证、PMP认证、红帽RHCE认证
  • 哈尔滨校区地址:哈尔滨市松北区世泽路689号 科技创新城4号楼405
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、Adobe认证、PMP认证、红帽RHCE认证
  • 南京校区地址:南京市建邺区应天大街780号弘辉产业园1栋2层
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、Adobe认证、PMP认证、红帽RHCE认证
  • 太原校区地址:太原市小店区长治路230号能源互联网大厦6层
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、Adobe认证、PMP认证、红帽RHCE认证
  • 沈阳校区地址:辽宁省沈阳市浑南区世纪路16号东大软件园B园B1座A201
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、Adobe认证、PMP认证、红帽RHCE认证
  • 合肥校区地址:合肥市包河区徽州大道396号东方广场B座12A
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、Adobe认证、PMP认证、红帽RHCE认证
  • 千锋教育服务号

    了解千锋动态
    关注千锋教育服务号

  • 千锋教育移动站

    扫一扫快速进入
    千锋移动端页面

  • 千锋互联服务号

    扫码匿名提建议
    直达CEO信箱

[an error occurred while processing the directive]