2019/10/07 03-匿名函数、生成器

在这里插入图片描述
匿名函数语法要求
没有名字可以定义出一个函数
必须有lambda
在这里插入图片描述
python借助lambda表达式构建匿名函数,要求必须有lambda关键字
lambda关键字 +参数列表 (不加括号)冒号作为分隔符,接着后面写表达式
lambda表达式,也叫匿名函数,有一个参数x,函数体是x
2 **
在这里插入图片描述
这样就可以调用
在这里插入图片描述
写高阶函数必须用到lambda表达式
这两个其实是一样的在这里插入图片描述
上下两个是等价的,foo都是作为标识符
在这里插入图片描述在这里插入图片描述匿名函数使用lambda关键字来定义
参数列表不需要小括号
冒号是用来分割参数列表和表达式的
不需要使用return,表达式的值,就是匿名函数返回值
lambda表达式只能写在一行上,被称为单行函数

在这里插入图片描述
都是非常简单的函数用lambda表达式
在这里插入图片描述
不管函数怎么调用就恒定一个return值
在这里插入图片描述
x,y=3默认值,:函数表达式部分
在这里插入图片描述
这是用y=keyword-only参数
在这里插入图片描述
这是生成器表达式,后面时传参,解构变成01,2,3,4被*args收集变成元组,被xfor x in args迭代,就是生成器表达式
最后return出来时生成器对象
生成器表达式生成的生成器对象

在这里插入图片描述
返回列表,里面+1,原来0123,4,现在是1-5
在这里插入图片描述
返回的是set
在这里插入图片描述在这里插入图片描述
in后面是要跟可迭代对象
range(5)=01,2,3,4传给 * args 组成元组01234,生成的参数扔给map函数,map函数是一个个处理,map处理以后一个个传入lambda表达式,把元素一个个+1
01234+1 = 12345,也是可迭代对象,塞入到里面去,得到列表{1,2,3,4,5】
map是生成类似一个迭代器的东西,是生成一个惰性求值的对象
、、在这里插入图片描述
是一个map得到的可迭代对象,扔给in,in就开始遍历,map是一个惰性求值的函数在这里插入图片描述
这是凑成一个元组返回了,这个一个个元组凑成x进行return
生成[(1),()]
在这里插入图片描述在这里插入图片描述
map函数的返回都回加1
\ 在这里插入图片描述
这是map的两个参数,第1参数,第2参数在这里插入图片描述
不要在后面用等号,不允许,出现赋值表达式
在这里插入图片描述
冒号后面属于lambda表达式的部分不能出现等号
在这里插入图片描述

之前是,用生成器表达式来得到一个生成器对象,但是表达式的能力比较有限,复杂的是完成不了,需要借助于语句
,能否用函数来得到生成器对象

generator生成器
在这里插入图片描述
生成器指的是生成器对象,可以由生成器表达式得到,也可以使用yield关键字得到一个生成器函数,调用这个函数得到一个生成器对象
生成器函数:
必须要求函数体由yield的语句
这个函数调用回返回一个生成器对象,生成器对象是一个可迭代对象,也是迭代器,可以用next方法,是惰性求值,什么时候用就给你算
在这里插入图片描述
生成器表达式可以得到一个生成器对象,就可以用next方法,拨一下做一下在这里插入图片描述
有了yield就不是普通函数,是生成器函数,如何得到生成器对象,必须进行调用在这里插入图片描述在这里插入图片描述
仿照来写生成器函数
生成器函数定义也是个函数,要得到生成器函数对象,就需要对函数进行调用
这个函数返回的是一个生成器对象

在这里插入图片描述
不管是生成器表达式还是生成器函数得到的,都是生成器对象,这个类型没变,生成器迭代完后不可回头,在拿一个新的生成器对象继续迭代
在这里插入图片描述在这里插入图片描述
for循环可以判断边界,再次迭代是否可以,不可以在这里插入图片描述
可以加缺省值来解决在这里插入图片描述
生成器函数是函数,(不跟其他函数一样,调用返回具体的值),而是返回一个还没有求过任何值的生成器对象,调用这个对象,拨一下转一下
x返回的类型就是生成器了在这里插入图片描述
*两个 *是看不到的,因为在前面已经走完 **
在这里插入图片描述在这里插入图片描述
在一个生成器函数中,既可以用yield又可以return
现在g是一个生成器对象,调用了生成器函数,拨一下转一下在这里插入图片描述在这里插入图片描述
再拨一下执行了这一句
在这里插入图片描述
对于next函数来讲,再生成器对象找下一个yield,碰到yield,把后面的值返回去,然后自己停止
(函数没有return,但是竟然停了)

如果把这个循环做一次次next
for循环再迭代过程中替你一次次next
在这里插入图片描述
拿到4之后在这里插入图片描述
再next试试,进不去循环,就return none回来,告诉你已经到头了,就会抛出异常
只不过for循环在替你做next
在这里插入图片描述
第一次,拨到yield1停了,第二次,到yield2停
在这里插入图片描述
line3打印了,但是后面的3没有拿到
return返回的值,next函数是不会给你的
next函数碰到return,告诉你没了,到头了,抛出个异常
在这里插入图片描述
对于一个生成器来讲,其实是可以用生成器表达式或者生成器函数来构造的,构造可以写多个或者一个yield语句,使用循环,看似是一个yield其实是多个yield
如果没有循环,可以写多个yield
生成器函数调用之后会产生一个生成器对象,你不用next,就没返回值
碰到yield的时候函数会暂停,会把yield后面跟的值拿出来交给next函数来返回,碰到return抛出异常,因为已经到头了

在这里插入图片描述在这里插入图片描述
没有显示的语句相当于return none,相当于结束,就会抛出异常
在这里插入图片描述
生成器函数必须包含yield语句,调用生成器函数,返回生成器对象,但是生成器对象是懒惰的,不是立即求值,不用next根本不会返回任何数据,哪怕里面有错误,不会报给你,因为没有语法错误,因为有语法错误是构建不出来的在这里插入图片描述
next在执行生成器的时候,会从函数当前位置或者上一次的位置,向后执行,当碰到yield语句的时候,会返回yield后面的值,并且暂停当前函数使用

执行完停止函数,再继续执行
在这里插入图片描述
如果再没有yield语句可以执行,就会抛出异常在这里插入图片描述在这里插入图片描述
c是个迭代器
c =counter()调用这个函数,会返回一个生成器对象、生成器对象扔到inc里去
next会拨一下走一下
在这里插入图片描述
这样就永远不会到头,死循环
在这里插入图片描述
第一次是1
第二次是1
因为下面每次都重置了,inc()

在这里插入图片描述在这里插入图片描述
后面加括号,肯定是个可调用对象
c=counter()
next(c)
形成了闭包,内层函数引用到了外层的函数

在这里插入图片描述
再多运行几次
调用相当于临时拨了生成器对象一下,一直在上一次的基础上走一趟
自始至终用的都是同一内存对象

在这里插入图片描述
把三个函数作为嵌套函数来完成一个功能
在这里插入图片描述
再进行改造一下
在这里插入图片描述
是等价的在这里插入图片描述
嵌套函数在一起可以完成比较复杂的功能

斐波那契数列的生成器版本,首先先写循环,循环写好封装成函数,然后在里面,yield出来值即可在这里插入图片描述
a,b=0,1起始值
在这里插入图片描述在这里插入图片描述
斐波那契数列的生成器版本做好了在这里插入图片描述
要考斐波那契数列,要么递归,要么生成器,必须记住
yield会函数暂停执行
在这里插入图片描述在这里插入图片描述
生成器函数能帮助外面写更加复杂的生成器对象,生成器表达式可以生成一个比较简单的生成器对象,更多的是使用生成器函数来创建一个生成器对象出来
生成器最大的好处是可以惰性求值
(列表解析式只要执行,就会把所有元素填到列表里了,列表立即返回)但是生成器是要一个给一个,不需要立即把所有值给你,这是惰性求值的好处,减少负担

yield可以暂停函数执行,这功能非常强大

**除了进程和线程,python,和ruby还提出了协程coroutine,这个用的好,你的效率会很高,而且轻量
是生成器的高级语法
是在用户空间进行调度的实现,线程无非就是执行个函数,只不过是在不太的线程中去执行,但是线程太多事有问题的,而且线程的切换是有问题的,尤其在python中,线程不见得效率很高。
这时候就提出了协程 coroutine
跟生成器有关系,就因为yield语句
python3提出了asyncio就是协程实现的,已经加入到标准库
**
在用户空间调度函数是什么概念,操作系统有内核空间和用户空间,这个协程不在操作系统和内核空间进行切换调度,
在用户空间就直接完成切换
(比如a线程执行完执行b线程,a进程执行完执行b线程,这两种操作都是要进内核空间的,但是协程不用再内核空间中去完成)
协程调度器实现思路,有两个函数,都有yield语句

第一个程序执行完执行下一个
在这里插入图片描述
改造一下
定义两个生成器函数

在这里插入图片描述在这里插入图片描述
再执行一次
在这里插入图片描述
相当于在外面加for循环
再次执行

在这里插入图片描述在这里插入图片描述在这里插入图片描述
跟线程差不多,线程做事情也是调度的,这是一种调度,轮询,最简单的策略,也是最常用的策略
线程进程也是需要调度的,但是都不是在用户空间完成的
协程是在用户空间完成的,协程的效率非常高,多线程的效率都未必有协程高

如果愿意可以自己写调度策略,执行a再执行b
在这里插入图片描述
非抢占式的,因为执行到yield之后才能暂停,后面才能进行调度
在这里插入图片描述
yield语句会暂停当前函数执行,让出控制权,交给外面调度的在这里插入图片描述
有yield就算生成器函数
在这里插入图片描述
是3.3出现的新语法
在这里插入图片描述在这里插入图片描述
函数定义跳过,inc(10)传进来,
counter(10)生成器对象,可以迭代,把里面的值迭代,写成yield from

在这里插入图片描述在这里插入图片描述在这里插入图片描述
递归,函数的调用过程,压栈,局部变量也压栈,函数调用完弹出,会把返回值给你,函数压栈理解之后,才能理解递归,压栈是由次数限制的,栈空间有限制的
每压一次函数,局部变量都有一大堆东西,栈空间很快就用满,是有限的,所以python是做了保护了
递归很容易自己调用自己,几千下过去了,cpython设定的保护是1000,要注意递归的深度问题,
自己调自己,或者间接调用自己,间接调用是非常危险的

注意斐波那契数列的递归写法这是最简单的,一定会问

匿名函数lambda比较简单,lambda表达式可以写复杂

生成器一定要注意惰性求值,yield语句本身可以暂停函数执行并且让出控制权,这个有了就可以用协程,生成器函数只要带yield就算,调用之后才会返回生成器对象
在这里插入图片描述在这里插入图片描述在这里插入图片描述
abcd,123ad,求公共字(ab)这样的,字符串是有连续的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回答: 在Python中,生成器是一种特殊的函数,它使用yield语句来产生一个序列的值。生成器函数可以通过定义一个普通函数,但使用yield语句来替代return语句来创建。生成器函数可以在需要的时候生成值,而不是一次性生成所有的值,这样可以节省内存空间。\[3\]而匿名函数是一种没有函数名的函数,它使用lambda关键字来定义。匿名函数通常用于简单的函数功能体,可以在一行代码中定义函数并返回结果,而不需要使用def语句来定义一个具名函数。\[1\]\[2\]匿名函数常常用于行内函数定义或者推迟执行一些代码。 #### 引用[.reference_title] - *1* [Python生成器的send方法、递推函数、匿名函数及常用内置函数](https://blog.csdn.net/qdPython/article/details/127983610)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [python数据结构之匿名函数lambda](https://blog.csdn.net/weixin_48077303/article/details/122315599)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [详解 Python 列表推导式|迭代器|生成器|匿名函数](https://blog.csdn.net/dQCFKyQDXYm3F8rB0/article/details/125418910)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值