程序员Python培训分享Python的递归函数和匿名函数调用。函数是Python技术学习的重要组成部分。深入掌握这个阶段的知识内容,对于Python技术能力的提升是很有帮助的。这里对递归函数和匿名函数两种函数调用进行系统的介绍和分析。1.递归函数 a)简介:如果在函数中调用自己会发生什么?就会陷入无限调用循环。解决这个问题需要用到递归。 b)应用: i。案例研究:编写一个接受整数n并计算输出n的阶乘的函数。 1。先定义一个函数deffactorial(n),这个函数应该怎么实现呢?我们知道n的阶乘的计算有如下规则:n!=n[(n-1)[n-2]…1]=n(n-1)! 2。函数实现步骤可以是: deffactorial(n): 1。计算(n-1) 2的阶乘。返回step1结果值*n 首先要做的是计算(n-1)!。由于我们的功能是计算n!,所以第一步也可以理解为以n-1为参数调用阶乘函数。代码将变为: deffactorial(n): 1.factorial(n-1) 2。返回step1*n 的结果值在这段代码中,出现了在factorial函数中调用阶乘函数的情况。发生函数递归。为了完善上面的代码,第二部分代码也可以翻译成代码: deffactorial(n): 1。int结果=阶乘(n-1) 2。returnresult*n 但是问题也出现了,加上n=3,fac(3)里面会调用fac(2),fac(2)里面会调用fac(1),fac(2)里面会调用facfac(1)(0)-》fac(-1)...因此,我们需要指定一个循环调用结束的条件。在当前程序中,当参数n的值为1时,计算1的阶乘。此时,就没有必要继续递归了。因此,如果n=1,应该直接返回。 deffactorial(n): if(n==1): return1 intresult=factorial(n-1) returnresult*n2.匿名函数 a)简介:当我们创建一个函数时,有时我们不需要显式定义函数。直接传入匿名函数更方便。这样可以省去我们给函数命名的麻烦,也可以少很多编程语言提供匿名函数的特性。匿名函数用得好,会起到画龙点睛的作用。如果用不好,很容易招虎成反狗。 b)在Python中使用lambda关键字创建匿名函数。所谓匿名,就是不再使用def的标准形式来定义函数。需要注意以下几点: i。lambda是一个表达式而不是代码块 ii。lambda表达式只能封装有限的函数逻辑 iii。Lambda函数有自己的命名空间 c)语法结构:lambda参数:lambdax:x*x等表达式,冒号前的x代表参数,后面代表函数的执行代码,,就是相当于下面的函数: Deff(x):returnx*x d)注: i。一个匿名函数只能有一个表达式 ii。写一个return语句,表达式的结果就是返回值 iii。匿名函数也是一个函数对象,可以赋值给一个变量,然后通过变量调用函数。f=lambdax:x*xf(6)3.推导:是一种独特的推导语法,在某些场合可以帮助我们写出更精简、更酷的代码。但没有它,也不会有太大的影响。 a)类别: i。列表理解 ii。词典理解 iii。集合理解 iv.元组推导? b)列表推导:是一种以方括号括起来的语句形式快速生成列表的方法。 我。案例:lis=[xxforxinrange(1,10)]先执行for循环,将每一个x放入xx中进行运算,将运算的结果值逐一添加到一个新的列表中(其中使用的变量x*x的公式必须是xinfor)。特别是,列表理解为我们提供了一种生成列表的方法,这些列表可以在一行中实现更复杂的逻辑。它的核心语法是用方括号封装生成的逻辑。 ii。案例:[x*xforxinrange(1,11)ifx%2==0]通过添加if语句 iii过滤x。案例:dic={“k1”:"v1","k2":"v2"}a=[k+":"+vfork,vindic.items()] c)字典推导:列表推导使用方括号,所以如果你使用大括号,你可以创建一个字典推导 i。case:dic={x:x2forxin(2,4,6)}x:x2中间的冒号左边表示key,右边表示value ii。案例:也可以加if子句 d)集合推导:花括号不仅可以作为字典推导,还可以作为集合推导,注意两者的区别。 我。case:a={xforxin“abcdefg”ifxnotin“abc”} e)元组推导:是不是带括号的元组推导?不。在python中有一种称为生成器的语法,它使用括号,在python中没有元组理解。 我。如果想通过类似上面的方法生成元组,需要显式调用元组的类型转换函数tuple。t=tuple(xforxinrange(10)) f)面试题: result=[lambdax:x+iforiinrange(10)] print(result0) 答案是19,result0~9的结果都是19。这是因为函数有调用时查找变量的属性。在您调用它之前,它不会保存或关心其内部变量的具体值。只有当你调用它时,它才会一一找到这些变量的具体值。当这里的result[0]被调用时,变量i已经循环完毕,变成了9,而不是想象中的动态0-9的值。 如果不想要这样的结果,想让i作为循环的值怎么办?不要直接引用上层变量,直接把变量传入即可 result=[lambdax,i=i:x+iforiinrange(10)] print(result0)4.迭代器 a)迭代:通过for循环元素遍历每个对象的过程。For可以迭代任何可迭代对象。 b)可迭代对象类型:list/tuple/string/dict/set/bytes。可以使用collections模块的Iterable类型判断一个对象是否可迭代: fromcollectionsimportIterable isinstance('abc',Iterable)#str是否可迭代 c)Iterator:Itisakindof被遍历的对象。特点如下: 我。可以调用next()函数。 ii。使用iter()函数创建一个迭代器对象 iii。迭代器对象从集合的第一个元素开始访问,直到访问完所有元素 iv。只能向后遍历,不能回溯 v。案例: >>>lis=[1,2,3,4] >>>it=iter(lis)#使用Python内置的iter()方法创建迭代器对象 >>>next(it)#使用next()方法获取迭代器的下一个元素 1 >>>next(it) 2 >>>next(it) 3 >>>next(it) 4 >>>next(it)#当next没有元素时,会报错 或者用for循环遍历迭代器: lis=[1,2,3,4] it=iter(lis)#创建迭代器对象 forxinit:#使用for循环遍历迭代对象 print(x,end="") 迭代器函数:除了可以迭代的iterable类型之外,一些自定义类型在开发时也有迭代需求,即定义自定义类型为迭代器类型(需要在class()方法中实现__iter__()和__next__,可以被next和iter函数调用)。for循环本质上是通过不断调用next()函数来实现的。 自定义迭代器类: importrandom classdemo_iterator(object): def__next__(self): v=random.randint(0,10) ifv<5: raiseStopIteration() else: returnv def__iter__(self): returndemo_iterator() 迭代函数:这个元素流可以看成是一个有序的序列,但是序列的长度无法预先知道,只能通过next()函数不断获取下一个元素,所以迭代器可以节省内存和空间.5.生成器 a)介绍:有时候,一个序列或集合中的元素数量非常多。如果全部制造出来放到内存中,对计算机的压力会非常大。例如,假设你需要获取一个巨大的10**20次方的数据序列,生成每个数并放入一个内存链表中。这是一种粗略的方式。有这么大的内存吗?如果元素可以按照一定的算法计算出来,在循环的过程中可以不断计算后面的元素,而不必创建完整的元素集合,这样就节省了大量的空间。在Python中,这种边循环边计算元素的机制被称为生成器:generator。 b)语法格式:类似推导,使用括号 c)大小写: >>>g=(x*xforxinrange(1,4)) >>>g 在0x1022ef630> 可以通过next()函数得到生成器的下一个返回值,这和迭代器很像: >>>next(g) 1 但在更多情况下,我们使用for循环。 foriing: print(i) d)关键字产量: 1.用法:yield返回的函数将成为生成器。在调用生成器的过程中,每次遇到yield,函数都会暂停并保存当前所有运行信息,并返回yield值。并在下次运行next方法时从当前位置继续执行。
