函数式编程是一种古老的编程模式,即用函数(计算)来表示程序,用函数的组合来表达程序组合的思维方式,最开始受到学术界的热捧,近年来开始在业界被投入使用。因此,越来越多的高级语言都加入对函数式编程的支持,python同样如此。

lambda表达式

lambda表达式可以创建一个匿名函数,对于一些使用频率低、结构简单的函数,使用lambda函数可以更为简洁

lambda语法

使用冒号(:)分割函数的参数及返回值:左边放函数的参数,若有多个参数用“,”号隔开,右边是函数返回值

lambda 参数1, 参数2 : 参数返回值

示例:

a = lambda x , y : 2 * x + y
a(3,4) #输出结果:10

若使用常规写法,则复杂一些:

def a(x,y):return 2 * x + y
a(3,4) #输出结果:10

除了简化函数之外,也可以将闭包转化为lambda表达式:

def funX(x):return lambda y : 2 * x + y
a = funX(5)
print(a(3)) #输出结果:13

总结

  1. lambda 定义了一个匿名函数
  2. lambda 并不会带来程序运行效率的提高,只会使代码更简洁,同时可能会降低一定可读性
  3. 如果可以使用for…in…if来完成的,坚决不用lambda
  4. 如果使用lambda,lambda内不要包含循环,如果有,尽量定义函数,使代码获得可重用性和更好的可读性

filter()

filter顾名思义,是一个筛选器。那这个是筛选什么呢?举个例子

filter(lambda x:x % 3 == 0, [i for i in range(100)])

这行代码先用列表表达式生成0-99的列表,然后将99个参数依次代入,将符合x%3==0(3的倍数)条件的参数筛选出来。运行结果为[3,6,9…,99]

filter()语法

filter(函数,参数集)

函数的返回值需要为True或False的布尔型数值或者是0 1。而参数集可以是元组,也可以是列表。
若函数为None,则直接筛选参数集

filter(lambda x:x % 3, (1,3,5,7,9,11,13,15))

该代码则返回除以3余数为1的数值

map()

map可以理解为映射。将参数集中的参数依次传递给函数加工,生成新的返回值集。
语法结构和filter类似:

map(函数,收集参数)

收集参数中支持多个可迭代对象,即多个参数集。依次从参数集中选出一个参数生成元组传递给函数。若各参数集长度不一致,则以较短的为准。举个例子:

map(lambda x, y : x + y, [1,2,3],[4,5,6,7,8])

在此处传递了两个参数集,实际上相当于将(1,4) (2,5) (3,6)传递给函数加工

那么,用通俗点的话就是:map是将众多参数一起给函数加工,而常规的for循环等则是一个一个给函数加工。那么,map到底是一批一批给函数加工,还是一次性全给函数加工?速度上到底差距多少呢?

from time import time
def mult(x):return x*x
max = 100000000a = [i for i in range(max)]
t0 = time()
for i in a:mult(i)
t1 = time()
print((t1-t0)*1000) #输出结果:26727.608680725098t2 = time()
map(mult,a)
t3 = time()
print((t3-t2)*1000) #输出结果:0.0

在该代码中(运行结果由电脑性能决定),定义了一个返回参数平方值的函数,同时为了放大结果差异,生成了一个0-99999999的列表,合计1亿个元素。一个用循环的写法,一个用map的写法,用time模块来记录两个方式运行的时间。

在程序中,可以很明显看出1亿个元素循环加工的话,需要运行的时间远远超过map方式。即使放大了1000倍仍然无法看到map运行的时间。而使用比值print((t1-t0)/(t3-t2))的话,竟然抛出ZeroDivisionError异常,即map的运行时间极短,短到time()方法几乎无法记录。

从逻辑上,整个流程大致如下:
【循环】计时——传入参数——加工——传入参数——加工——……——停止计时——输出时间
【map】计时——传入参数——加工——停止计时——输出时间
可以看出,一个是一个一个加工,一个是同时加工

递归

递归(英语:Recursion),又译为递回,在数学与计算机科学中,是指在函数的定义中使用函数自身的方法。递归一词还较常用于描述以自相似方法重复事物的过程。例如,当两面镜子相互之间近似平行时,镜中嵌套的图像是以无限递归的形式出现的。也可以理解为自我复制的过程。【by维基百科】

谢尔宾斯基三角形就是一个递归形成的图形

递归通俗点说,就是函数运行中再次调用函数。就像在接力赛中,自己的一棒跑完了又传给自己接着跑。那么递归在程序中如何体现呢?
求阶乘:

def factorial(n):if n == 1:return 1else:return n*factorial(n-1)
number = 5
print(factorial(number)) #输出结果:120

可以看到,在当n!=1时,函数的返回值中再次调用了自己,而if语句则是用来跳出递归的条件。假如我们在程序中,不添加跳出语句,那么递归会一直运行下去,直到把内存全部消耗完,这样的程序无疑是失败的。在python中,对于递归深度是有默认限制的,所以并不会真的把内存全部消耗完才停止,当递归到指定限制的深度时,程序就会自动停止。若是应用在爬虫方面,当爬虫需要爬很深时,就需要自行设置递归深度了:

import sys
sys.setrecursionlimit(10000) #设置递归深度为10000

虽然可以自行设置递归深度,但是当递归深度很大时,同样可能出现过度消耗资源而崩溃。可以通过ctrl+C强行停止

斐波那契数列

在数学中有一个数列叫做“斐波那契数列”,即该位置的数等于前两个数的和。该数列是由兔子繁殖引出的:假设在一个地方有一对兔子,且每只兔子都不会死去,这里也没有兔子的天敌;兔子出生两个月后就有了繁殖能力,每个月都能生一对兔子,那么n月之后有多少对兔子?
数字表现形式为:1,1,2,3,5,8,13,21,34……
这个问题用常规写法,需要创建三个变量,分别表示前两个月,前一个月,本月的兔子数,最后通过条件判断,通过循环实现计算。但是使用递归,整个问题就很简单了:

def fab(n):if n < 1:print('n>=1')return -1if n == 1 or n == 2:return 1else:return fab(n-1) + fab(n-2)
print(fab(12)) #输出结果:144

事实上,使用递归解决问题的时间,并不比迭代快,甚至若cpu性能一般的话,差距会更大。显然,在这种逻辑比较明显的问题上,递归比迭代间接,但是运行时间反而更长。

汉诺塔难题

但是当碰到汉诺塔难题,常规写法就非常复杂了。汉诺塔即三根杆,第一根杆套有n个圆盘,要求所有圆盘叠放都符合小盘在上大盘在下,一次只能移动一个圆盘,将第一根杆的所有圆盘移动至第三根杆。显然,这种问题用常规解法一脸懵(反正我是一脸懵),但是用迭代就可以比较简单实现了:
假设三根杆为A,B,C,移动第n个圆盘可以分解为三步:
(1)将前n-1个圆盘移动至B杆
(2)将第n个圆盘移动至C杆
(3)将B杆的前n-1个移动至C杆
那么,移动n-1个圆盘,也可以分解为三步:
(1)将前n-2个圆盘移动至C杆
(2)将第n-1个移动至B杆
(3)将C杆的前n-2个移动至B杆
那么问题很明显了,移动第n个圆盘都有固定的步骤。所以我们只需要正确地传递n,A,B,C参数,就可以通过迭代的方式实现汉诺塔的移动:

def hanoi(n,a,b,c):if n == 1:print(a,'->',c) #若只有一个,则直接移动else:hanoi(n-1,a,c,b) #将前n-1个从a移动至bprint(a,'->',c) #移动第n个hanoi(n-1,b,a,c) #将前n-1个从b移动至c
hanoi(4,'A','B','C')

函数中的a表示第n个的起始位置,c表示第n个的终止位置,b表示中间存放n-1个的位置

所有的循环都能写成递归(加上跳出条件即可),但是所有的递归不能都写成循环

python 函数式编程及递归相关推荐

  1. 函数式编程语言python-10分钟学会python函数式编程

    原标题:10分钟学会python函数式编程 在这篇文章里,你将学会什么是函数范式以及如何使用Python进行函数式编程.你也将了解列表推导和其它形式的推导. 函数范式 在命令式范式中,通过为计算机提供 ...

  2. python编写函数_浅谈Python 函数式编程

    匿名函数lambda表达式 什么是匿名函数? 匿名函数,顾名思义就是没有名字的函数,在程序中不用使用 def 进行定义,可以直接使用 lambda 关键字编写简单的代码逻辑.lambda 本质上是一个 ...

  3. python采用函数编程模式_浅谈Python 函数式编程

    匿名函数lambda表达式 什么是匿名函数? 匿名函数,顾名思义就是没有名字的函数,在程序中不用使用 def 进行定义,可以直接使用 lambda 关键字编写简单的代码逻辑.lambda 本质上是一个 ...

  4. Python 函数式编程,从入门到放弃

    很早以前就听说过了函数式编程,印象中是一种很晦涩难懂的编程模式,但却一直没有去进行了解. 恰好这周组内的周会轮到我主持,一时也没想到要分享什么.灵光一闪,就选定函数式编程这个主题吧,反正组里的同事都没 ...

  5. python采用函数式编程模式-浅谈Python 函数式编程

    匿名函数lambda表达式 什么是匿名函数? 匿名函数,顾名思义就是没有名字的函数,在程序中不用使用 def 进行定义,可以直接使用 lambda 关键字编写简单的代码逻辑.lambda 本质上是一个 ...

  6. Python函数式编程——map()、reduce()

    提起map和reduce想必大家并不陌生,Google公司2003年提出了一个名为MapReduce的编程模型[1],用于处理大规模海量数据,并在之后广泛的应用于Google的各项应用中,2006年A ...

  7. python函数式编程读取数据-python学习笔记9:函数式编程

    函数式编程(FunctionalProgramming) 基于lambda演算的一种编程方式 程序中只有函数 函数可以作为参数,同样可以作为返回值 纯函数式编程语言: LISP, Haskell Py ...

  8. Python函数式编程简介(二)返回函数

    本文为Python函数式编程的第二部分主要讲解返回函数和闭包 2.返回函数 2.1.函数作为返回值 高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回. 我们来实现一个可变参数的求和.通常 ...

  9. Python函数式编程简介(一)高阶函数

    本文概括介绍Python函数式编程的一些概念及用法,详细请参考: https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df ...

最新文章

  1. python基础知识05-控制流程
  2. html5 注册协议弹出层,js制作带有遮罩弹出层实现登录注册表单特效代码分享
  3. 总结一下目标检测与跟踪
  4. matlab 2020b linux版本 下载
  5. matlab进行多光栅衍射仿真,光栅衍射MATLAB仿真.docx
  6. kdj指标主要看哪个值_史上最全KDJ指标用法详解,学习KDJ指标看这一篇就够了
  7. 子列和列_最大子列和的四种算法总结
  8. 项目管理工具四、有效管理的PDCA原则
  9. 微信指纹支付原理浅析
  10. 解决在VsCode中使用CodeRunner中文乱码
  11. Microservice Patterns 下载
  12. linux文件夹怎么恢复默认打开方式,怎么还原打开方式_在win7电脑上还原文件默认打开方式的步骤 - 驱动管家...
  13. 解决PHP项目显示“该网页无法正常运作”,但没有显示报错内容
  14. Isomorphic 同构树(图)的实现
  15. 盘点那些冷门又有趣的大学专业,你的学校有啥奇葩专业?
  16. 学编程,自学还是选择培训机构?
  17. matlab 区域生长算法生成二值图像边界区域
  18. MATLAB之function函数
  19. 八爪鱼软件爬取数据的操作流程
  20. 计算机主机显卡安装,电脑如何安装独立显卡|电脑安装独立显卡的方法

热门文章

  1. Storm学习(一)Storm介绍
  2. eMMC ext4综述【转】
  3. 将两个有序顺序表合并为一个新的有序顺序表MergeList_Sq
  4. 博图软件备份程序监控数据
  5. 如何反制互联网精准广告定向
  6. NCBI RefSeq命名格式的详细说明
  7. 【原创】简单介绍 Windows XP 中的chkdsk(checkdisk磁盘检查)工具
  8. 斐讯n1刷linux服务器,斐讯N1刷Ubuntu系统配置SMB
  9. linux批量替换文件内容
  10. android如何绑定事件,Android_安卓为按钮控件绑定事件的五种方式