day19:生成器、yield表达式、三元表达式、生成式和函数的递归

news2024/9/21 21:15:38

一、生成器

1. 如何得到自定义的迭代器

【方法一】:在函数内一旦存在yield关键字,调用函数并不会执行函数体代码,会返回一个生成器对象,生成器即自定义的迭代器
【方法二】:生成器表达式

反问:为什么自定义的迭代器叫做生成器 ???
答:这是 规定 !!!

'''案例说明:'''

def func():
    print('第一次运行:')
    yield 1
    print('第二次运行:')
    yield 2
    print('第三次运行:')
    yield 3

g = func() # 存在yield,调用函数func时并没有执行函数,而是得到了一个生成器对象
print(g)  # <generator object func at 0x0000029CDF636030>

'''2、解释生成器即为迭代器'''
#注意看下面的调用,g这个生成器对象有__iter__()和__next__()方法,说明g也是迭代器对象,印证了“生成器即自定义的迭代器”这句话
# g.__iter__()
# g.__next__()

'''3、函数调用'''
# g.__next__()    # 仅仅取一个值,遇到yield时鼠标光标会停留在yield返回值的后面,这里是停在了 1 后面;
# print(g.__next__())   # 运行这一行时注释g.__next__(),print(g.__next__())输出值为2;
def func():
    print('第一次运行:')
    yield 1
    print('第二次运行:')
    yield 2
    print('第三次运行:')
    yield 3

g = func()
g.__next__()   # 第一个yield返回值没有被接收和打印
#>输出:第一次运行:
print(g.__next__())    # 第二个yield返回值有被接收和打印
#>输出:
#    第二次运行:
#    2

2. 函数本身方法的使用,例如g.next(),等价于netx(g)

len('aaa') # 等价于 'aaa'.__len__()

next(g)    # 等价于 g.__next__()
iter(可迭代对象)     #等价于 可迭代对象.__iter__()

3. 总结yield

有了yield关键字,我们就有了一种自定义迭代器的实现方式。yield可以用于返回值,但不同于return,函数一旦遇到return就结束了,而yield可以保存函数的运行状态挂起函数,用来返回多次值

二、yield表达式

1、x =yield ,后面不接返回值,即返回None

x = yield None

2、注意:给生成器传值,实际上是传给了yield,yield再将接收的值赋值给x

'''案例:学习函数体有yield关键字时的代码执行逻辑'''
def people(name):
    print('大飞飞%s准备吃东西啦...' %name)
    while True:
        x = yield None
        print('大飞飞%s吃了 %s' %(name,x))

g = people('lulucy')  # 得到了一个迭代器对象,因为函数体有yield,所以也叫做生成器
print(g)   # 输出:<generator object dog at 0x000001D33ACD5F50>

res = next(g)   # 第一次执行next或send,是触发函数体的运行,执行到x=yield时鼠标光标会移动到x=yield正后方,返回值为None(打印res可知),等待生成器再一次传值,代码被挂起
print(res)  # 获取到yield后面的返回值None

print('=========================')

next(g)  # 触发代码继续运行,先执行“print('大飞飞%s吃了 %s' %(name,x))”,执行到下一个循环到yield时代码再次挂起,等待下一次传值
g.send('鸡公煲')  # yield接收到的值为“鸡公煲”,此时将“鸡公煲”赋值给了x,出发代码继续运行,再次执行“print('大飞飞%s吃了 %s' %(name,x))”
g.send('三鲜煲')
g.close()        # 关闭生成器对象,后面无法继续传值
g.send('1111')   # 继续传值报错,StopIteration

三、三元表达式

【语法格式】: 条件成立时要返回的值 if 条件 else 条件不成立时要返回的值

1.举例:需求为比较两个数大小,引出三元表达式

'''案例:比较两个数大小'''

def func(x,y):
    if x > y:
        return x
    else:
        return y

res=func(1,2)
print(res)

2.使用三元表达式简化代码

def func(x, y):
    res = x if x > y else y
    return res

print(func(11,22))

四、生成式

4.1 列表生成式

'''需求:筛选出含有dsb的名字'''

l = ['alex_dsb', 'lxx_dsb', 'wxx_dsb', "xxq_dsb", 'egon']
new_l=[]

'''常规写法'''
for name in l:
    if name.endswith('dsb'):
        new_l.append(name)
print(new_l)

'''列表表达式'''
#筛选出含有dsb的名字
new_l = [name for name in l if name.endswith('dsb')]
print(f'列表表达式写法输出结果:{new_l}')

'''循环列表取值'''
new_l=[name for name in l] #  # 等价于 new_l = [列表.append(name) for name in l]
print(f'列表表达式遍历列表   :{new_l}')

# 把所有小写字母全变成大写
new_l = [name.upper() for name in l]
print(f'把所有小写字母全变成大写:{new_l}')

# 把所有的名字去掉后缀'_dsb'
new_l = [name.replace('_dsb', '') for name in l]
print(f'把所有的名字去掉后缀"_dsb":{new_l}')

4.2 字典生成式

keys=['name','age','gender']
dic={key:None for key in keys} # 将遍历出的列表值传给key,这里不加条件默认是true ==>等价于dic={key:None for key in keys if true},
print(dic) # {'name': None, 'age': None, 'gender': None}

'''去掉列表中含有gender的项'''
items=[('name','egon'),('age',18),('gender','male')]
res={k:v for k,v in items if k != 'gender'}  # for循环先取出一个个元组,然后解压赋值给k和v,如果k不等于gender,则解压赋值传给k:v
print(res) # {'name': 'egon', 'age': 18}

4.3 集合生成式

keys=['name','age','gender']
set1 = {k for k in keys} # 等价于set1 = {集合.append(k) for k in keys }
print(set1, type(set1))  # {'name', 'age', 'gender'} <class 'set'>

4.4 生成器表达式

创建一个生成器对象有两种方式,一种是调用带yield关键字的函数,另一种就是生成器表达式

'''错误案例:无元组生成式,小括号是生成器表达式'''
#说明:元组没有append用法,所以不存在元组生成式

g = (i for i in range(1,10)) # 等价于 g = (元组.append(i) for i in range(1,10))
print(g)  # <generator object <genexpr> at 0x0000013BD06145F0>
'''正确案例:生成器表达式'''

g = (i for i in range(10))

# !!!!!!!!!!!强调!!!!!!!!!!!!!!!
# 此刻g内部一个值也没有
print(g) # 得到一个生成器对象,<generator object <genexpr> at 0x7f1766c90660>

print(g.__next__()) # 0
print(g.__next__()) # 1
print(next(g))      # 2
print(next(g))      # 3
print(next(g))      # 抛出异常StopIteration

结论:如果range()里面是一个无穷大的数,for i in range(无穷大) 打印x的话会很占内存,对比列表生成式,生成器表达式的优点自然是节省内存(因为一次只产生一个值在内存中),如果没值则抛出StopIteration异常

思考:读取大文件内容,是一行行读取然后存到列表还是使用生成器读?

需求:读取文件,计算出文件中一共有多少个字符

案例:分别使用常规写法、列表表达式、生成器表达式读取文件中所有的字符长度总和

须知:sum()内置函数,传入的需要是可迭代对象
在这里插入图片描述

'''案例:传入sum里面的是可迭代对象,'''
# print(sum(1,2,3,4))  # TypeError: sum() takes at most 2 arguments (4 given)

print(sum([1,2,3,4,5,6])) # 21
'''案例说明'''

with open('aaa.txt', mode='rt',encoding='utf-8') as f:
# # 方式一:常规写法
    res=0
    for line in f:
        res+=len(line)
    print(f'方式一:{res}')

with open('aaa.txt', mode='rt',encoding='utf-8') as f:
# # 方式二:使用列表表达式,缺点是如果行数过多,列表里面的数也会过多,占内存
    res1 = 0
    res1 = sum([len(line) for line in f])
    print(f'方式二:{res1}')

with open('aaa.txt', mode='rt',encoding='utf-8') as f:
# # 方式三:使用生成器表达式,最简洁
    res2 = 0
    # g =(len(line) for line in f)   # 得到了一个可迭代对象
    # print(g)  # <generator object <genexpr> at 0x0000022A97EB45F0>
    
    # res2 = sum((len(line) for line in f)) # 等价于下方
    sum(len(line) for line in f)  # 等价于sum(g)
    print(f'方式三:{res2}')

五、函数的递归

一:递归的定义

函数的递归调用:是函数嵌套调用的一种特殊形式
具体是指:在调用一个函数的过程中又直接或者间接地调用到本身

递归算法:
1.函数直接或者间接调用自身
2.必须具有递归结束条件
3.每一次递归,问题规模缩小
4.python限制了递归深度(sys.getrecursionlimit())

5.1 直接调用本身

def f1():
    print('是我是我还是我')
    f1()
f1()

5.2 间接接调用本身

def f1():
    print('===>f1')
    f2()

def f2():
    print('===>f2')
    f1()

f1()

5.3 一段代码循环运行的两种方案

方式一:while、for循环
while True:
    print(1111)
    print(2222)
    print(3333)
方式二:递归的本质就是循环:
def f1():
    print(1111)
    print(2222)
    print(3333)
    f1()
f1()

二:需要强调的的一点

【注】:递归调用不应该无限地调用下去,必须在满足某种条件下结束递归调用

n=0
while n < 10:
    print(n)
    n+=1


def f1(n):
    if n == 10:
        return
    print(n)
    n+=1
    f1(n)

f1(0)

三:递归的两个阶段

回溯:一层一层调用下去(注:回溯即递归调用,终止回溯即终止递归调用)
递推:满足某种结束条件,结束递归调用,然后一层一层返回

# age(5) = age(4) + 10
# age(4) = age(3) + 10
# age(3) = age(2) + 10
# age(2) = age(1) + 10
# age(1) = 18

def age(n):
    if n == 1:
        return 18
    return age(n-1) + 10


res=age(5)
print(res)

在这里插入图片描述

四:递归的应用

'''案例1:列表l中再叠加1层列表'''

l = [1,2,3,[4,5]]

for i in l:
    if type(i) ==list:
        for a in i:
            if type(a) ==list:
                pass
                # ..... 如果迭代很多层怎么办?我们发现重复执行的代码即函数本身,重复调用函数本身
                # .....
            else:
                print(a)
    else:
        print(i)
'''案例2:叠加很多层'''

l=[1,2,[3,[4,[5,[6,[7,[8,[9,10,11,[12,[13,]]]]]]]]]]

def f1(list1):
    for x in list1:
        if type(x) is list:
            # 如果是列表,应该再循环、再判断,即重新运行本身的代码
            f1(x)
        else:
            print(x)

f1(l)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2068809.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

信息系统安全等级划分及其重要性:构建安全基石

在信息化社会&#xff0c;数据已成为企业与国家的重要资产&#xff0c;其安全防护日益受到重视。我国的“信息系统安全等级保护制度”正是在这一背景下应运而生&#xff0c;旨在通过等级划分&#xff0c;为不同级别的信息系统提供适配的安全保护措施&#xff0c;确保信息资产的…

Camera篇(一)ov13850调试

ov13850一千三百万像素&#xff0c;必须离线模式&#xff0c;所以ISP TDM配置离线 menuconfig 中需要将ISP TDM功能打开&#xff0c;同时开启WDR 配为&#xff08;*&#xff09; dts配置 work_mode 一律配1 &vind0 {csi_top <360000000>;csi_isp <322000000…

基于x86 平台opencv的图像采集和seetaface6的眼睛状态检测(睁眼,闭眼)功能

目录 一、概述二、环境要求2.1 硬件环境2.2 软件环境三、开发流程3.1 编写测试3.2 配置资源文件3.2 验证功能一、概述 本文档是针对x86 平台opencv的图像采集和seetaface6的眼睛状态检测(睁眼,闭眼)功能,opencv通过摄像头采集视频图像,将采集的视频图像送给seetaface6的眼睛…

【C++ Primer Plus习题】3.4

问题: 解答: #include <iostream> using namespace std;const int DAY_TO_HOUR 24; const int HOUR_TO_MIN 60; const int MIN_TO_SEC 60;int main() {long seconds 0,record0;int days 0, hours 0, minutes0;cout << "请输入秒数:";cin >>…

进阶-5.锁

锁 1.概述2.全局锁3.表级锁3.1 介绍3.2 表锁3.3 元数据锁3.4意向锁 4.行级锁 1.概述 分类 按锁的粒度分类&#xff1a; 全局锁&#xff1a;锁住数据库中所有表表级锁&#xff1a;每次操作锁定整张表行级锁&#xff1a;每次操作锁定对应的行数据 2.全局锁 介绍 全局锁就是对…

【经验】linux下cuda的更换

linux下cuda的更换 查看当前cuda和cudnn的版本 nvcc -Vcudnn版本 cat /usr/local/cuda/include/cudnn.h | grep CUDNN_MAJOR -A 2下载对应版本的cuda 查看驱动版本535.54.03 下载对应的cuda版本 版本查看https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.htm…

Revisiting PM-Based B+-Tree With Persistent CPU Cache——论文泛读

TPDS 2024 Paper 论文阅读笔记整理 问题 持久存储器&#xff08;PM&#xff09;具有接近DRAM的性能和数据持久性&#xff0c;配备PM的平台支持异步DRAM刷新&#xff08;ADR&#xff09;功能[2]&#xff0c;确保PM DIMM的内容以及已到达内存控制器的写挂起队列&#xff08;WPQ…

深度学习 --- VGG16卷积核的可视化(JupyterNotebook实战)

VGG16卷积核的可视化 在前一篇文章中&#xff0c;我对VGG16输入了一张图像&#xff0c;并实现了VGG16各层feature map的可视化。深度学习 --- VGG16各层feature map可视化(JupyterNotebook实战)-CSDN博客文章浏览阅读615次&#xff0c;点赞13次&#xff0c;收藏15次。在VGG16模…

123-域防火墙入站出站规则不出网隧道上线组策略对象同步

参考&#xff1a;【内网安全】 域防火墙&入站出站规则&不出网隧道上线&组策略对象同步_对公司的邮件服务器建立防火墙规则 入站出战-CSDN博客 单机-防火墙-限制端口出入站 熟悉常见主机配置不出网的方式 1、入站&出站&连接安全 2、域&专用&公网…

【采集软件】用Python开发的小红薯详情批量采集工具,含笔记正文、转评赞藏等

一、背景介绍 1.1 爬取目标 用python开发的爬虫采集软件&#xff0c;可自动按笔记链接抓取笔记的详情数据。 为什么有了源码还开发界面软件呢&#xff1f;方便不懂编程代码的小白用户使用&#xff0c;无需安装python&#xff0c;无需改代码&#xff0c;双击打开即用&#xff…

本地部署docker文档

由于访问 https://docs.docker.com/ 文档慢&#xff0c;直接本地部署官方文档 如果不想执行以下操作&#xff0c;也可以直接使用官方文档仓库地址提供的 Dockerfile 和 compose.yaml 进行操作 以下操作环境为Windows系统&#xff0c;根据 Dockerfile 相关操作来生成 html 页面…

二叉树【1】

操作 新建节点&#xff08;new&#xff09; 新建一个值为v的节点&#xff0c;左右孩子NULL 查找 void查找函数 { 递归边界&#xff1a;NULL&#xff0c;然后退出 &#xff08;return&#xff1b;&#xff09; 查找左子树 查找柚子树 } 插入 void 插入函数 {…

Vue表单元素绑定:v-model 指令

Vue 指令系列文章&#xff1a; 《Vue插值&#xff1a;双大括号标签、v-text、v-html、v-bind 指令》 《Vue指令&#xff1a;v-cloak、v-once、v-pre 指令》 《Vue条件判断&#xff1a;v-if、v-else、v-else-if、v-show 指令》 《Vue循环遍历&#xff1a;v-for 指令》 《Vue事件…

NPM:配置阿里镜像库

1、配置阿里云镜像源 #查看当前使用的镜像地址命令 npm config get registry#设置阿里镜像源 npm config set registry http://registry.npmmirror.com 这里要注意下&#xff0c;之前的源镜像地址 https://registry.npm.taobao.org/ 已经不能用了&#xff0c;这里要更改为新地…

80页PPT数据中台应用技术实施方案

本文资料完整版81页PPT&#xff0c;下载完整PPT资料&#xff0c;知识星球APP搜索【智慧方案文库】&#xff0c;下载“数据中台”合集资料&#xff0c;以及8800份解决方案 数据中台设计的方法 (1)基于面向服务的架构方法&#xff08;SOA&#xff09; 基于面向服务的架构方法 …

spring整合redis

1.导入依赖 <!-- spring-data-redis 依赖--> <dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-redis</artifactId><version>2.7.18</version> </dependency> <dependency><…

旧衣回收小程序系统,为市场发展提供新模式

随着绿色生活的兴起&#xff0c;回收成为了大众生活的新选择&#xff0c;其中旧衣物回收更是深入人心&#xff01;通过旧衣物回收&#xff0c;大众不仅可以减少浪费&#xff0c;也能够进行资源在利用。目前&#xff0c;在科技的支持下&#xff0c;旧衣物回收正以一种新的方式进…

机械学习—零基础学习日志(如何理解概率论6)

随机变量的数字特征——期望与方差 以小明的成绩为例&#xff0c;如图所示。 这里其实涉及到&#xff0c;数学期望的概念。 对应的数值&#xff0c;乘以概率&#xff0c;相加以后就得到了数学期望。 随机变量的数学期望与方差 、 来个练习题&#xff1a; 解析&#xff1a; …

自制多肉查询工具

背景&#xff1a; 复习python qt、网页解析的常用操作 准备&#xff1a; 多肉信息网站涉及python的第三方库&#xff1a; lxmlPyQt5 实现效果&#xff1a; 功能&#xff1a; 随机读取&#xff1a;从本地加载已存储的多肉信息数据更新&#xff1a;从多肉信息网站更新5条多…

QT:Qt与ECharts

介绍ECharts ECharts是一款基于JavaScript的数据可视化图表库&#xff0c;由百度团队最初开发&#xff0c;并在2018年初捐赠给Apache基金会&#xff0c;成为ASF孵化级项目。随着项目的不断发展&#xff0c;ECharts在2021年1月26日正式毕业&#xff0c;成为Apache顶级项目 链接…