python学习Day21

Day 21

今日内容概要

  • 异常捕获
    • 异常捕获含义
    • 异常捕获多种语法结构
    • 异常捕获练习
  • 自定义迭代器对象(生成器对象)
    • 自定义迭代器对象(生成器对象)含义
    • 自定义迭代器对象(生成器对象)练习
    • yield的其他用法
    • 生成器表达式

今日内容详细

1.异常捕获含义
1.什么是异常
	程序在运行的中如果出现异常就会导致整个程序的结束
    异常在程序员中也叫'bug'
    
2.异常的结构
Traceback (most recent call last):
   File "D:/pythonProject/day20/lx1.py", line 1, in <module>
     name
NameError: name 'name' is not defined
    1)line 1#异常所在行
    2)最后一行冒号左侧#错误的类型
    3)最后一行冒号右侧#错误的具体原因,也是改bug的关键
    
3.异常的类型
    NameError#名称错误
    IndexError#索引错误
    KeyError#键错误
    SyntaxError#语法错误
    TypeError#类型错误

4.异常的分类
    1)语法错误
    	语法错误不允许出现,出现了必须马上修改(工作会扣钱)
    2)逻辑错误
    	可以出现,出错后修改就可以
  #ps写完代码自己一定要过一遍然后再提交
2.异常捕多种语法结构
1.什么时候才需要自己写代码处理异常?
	当代码不确定什么时候会报错的时候
    eg:编写网络爬虫访问网址数据并处理,有可能会出现断网数据没有,处理不了
        
2.异常捕获的使用相当于提前预测可能出现的问题并提前给出解决的措施

3.异常捕获的代码实现
	3.1.基本语法结构
    try:
       可能会出错的代码(被try监控)
    except 错误类型1 as e: #e是具体错误的原因
        对应错误类型1的解决措施
    except 错误类型2 as e: #e是具体错误的原因
        对应错误类型2的解决措施
        	...
            
  	3.2.万能异常(笼统的处理方式)
    try:
    	可能会出错的代码
    except Exception as e:#万能异常1什么类型都能显示
        print(e)
    except BaseException as e:#万能异常2类型都能显示
        print(e)
4.异常捕获其他操作补充
   4.1. else和finally 
    try:
        name
    except Exception as e:
        print('出错了')
    else:
        print('监测的代码没有出错正常运行结束后执行else子代码')
    finally:
        print('监测的代码无论有没有错都执行finally子代码')
   4.2.断言#预测接收的数据是什么类型,如果不对就报错,对就正常执行
        name='jason'#通过各种方式获取来的数据
        assert isinstance(name,list)#预测数据类型属于列表
        print('针对nmae数据使用列表的相关操作')#如果是列表则执行,不是列表就报错
   4.3.主动报错
		name=input('输入姓名:').strip()
    	if name == 'jason'
        	raise Exception('我报错了')#如果是jason则报错 异常名称为万能异常,也可以选其他
         else:
            print('没事执行吧')#如果不是则继续执行
            
 5.强调
	1)异常捕获能少用就少用
	2)被try检测的代码能少就少
#因为写的代码是要看代码内部功能,监测语法会消耗更多资源
3.异常捕获练习
1.for循环内部的本质
   #需求:使用while+异常捕获实现for循环的功能
    l1=[1,2,3,4,5,6]
    res=l1.__iter__()
    while True:
        try:
            print(res.__next__())
        except Exception as e:
            break
            
2.实际项目出现问题处理流程:
    '''
    1.先看具体的报错信息
    2.再看具体的定位信息
        由下往上查看
    3.尽量将错误缩小到某个具体的位置
    4.注意力关注在出现这个位置的代码身上
    '''
4.自定义迭代器对象(生成器对象)
1.生成器本质就是迭代器对象
	只不过迭代器是解释器提供给我们的(现成的)
	生成器是我们自己定义出来的(自己动手)
       迭代器对象特点:__iter__和__next__
2.学习生成器对象的目的就是为了优化代码
	1)一种不依赖于索引取值的通用方式
	2)可以节省数据类型的内存占用空间(主要)
3.生成器对象代码实现:
    def index():
        print('张三')
        yield#当函数体代码中有yield关键字时,函数名第一次加括号不会调用函数体代码,而是由普通的函数变成了迭代器对象(生成器)
        print('张三2')
        yield

    print(index)  # <function index at 0x000001F499F7A5E0>
    res = index()#该函数返回值被变量名接收后就变成了生成器对象(自定义迭代器对象)
    print(res)  # <generator object index at 0x0000021E18BACA50>
    res.__next__()#张三
    res.__next__()#张三2
    res.__next__()#一个yield只能执行一次 再来一次就报错 除非有多个yield
    '''
    每次调用__next__方法都会从上往下依次执行,直到遇到yield代码就停留在此处,再调用一次继续执行
    '''
——————————————————————————————————————————————————
    def index():
    	print('张三')
    	yield 123

	res = index()
	print(res.__next__())#张三 123
    '''
    yield后可以跟数据值 会像return一样返回出去,当有多个数据值逗号隔开时,会自动组织成元组返回
    '''
5.自定义迭代器对象(生成器对象)练习
1.编写生成器 实现和range()一样的方法功能
def my_range(start, end=None,step=1):#range内可以传三个参数
    if step <1:
        step=1#如果用户第三个数小于1则让其改为1
    if not end:#当用户没有给end传值时执行下列代码
        end = start #结束数变为开始数
        start=0 #开始数改为0
    while start < end:
        yield start
        start += step#step时用户第三个数输入多少就自增多少
for i in my_range(1,50,-3):
    print(i)

6.yield其他用法
#除了可以让函数变成生成器外还可以利用yield去接收数据
eg:
def index(name,food=None):
    print(f'{name}准备吃饭')
    while True:
        food = yield
        print(f'{name}正在吃{food}')
res=index('jason')
res.__next__()#jason准备吃饭
res.send('米饭')#jason正在吃米饭 send()传值并自动调用__next__方法
res.send('鸡腿')#jason正在吃鸡腿 send()传值并自动调用__next__方法
#send功能:给yield前面传一个值,然后自动来调用一个__next__()
7.生成器表达式
l1 = [i**2 for i in range(10) if i > 3]#列表生成式
print(l1)#[16, 25, 36, 49, 64, 81]

l1 = (i**2 for i in range(10) if i > 3)#生成器表达式
print(l1)#<generator object <genexpr> at 0x000001A793439C10>
print(l1.__next__())#16
print(list(l1))#[16, 25, 36, 49, 64, 81]
面试题
def add(n, i):  # 普通函数 返回两个数的和  求和函数
    return n + i
def test():  # 生成器
    for i in range(4):
        yield i
g = test()  # 激活生成器
for n in [1, 10]:#列表中只用1和10两个数
    g = (add(n, i) for i in g)#生成器里的代码只有被for循环或双下next时才会走
    """
    第一次for循环
        g = (add(n, i) for i in g)
    第二次for循环
        g = (add(n, i) for i in (add(n, i) for i in g))
    """
res = list(g)#调用时就把n改为10 
print(res)

#A. res=[10,11,12,13]
#B. res=[11,12,13,14]
#C. res=[20,21,22,23] √
#D. res=[21,22,23,24]
ps:掌握技巧即可 无需深究 纯粹为了考试而出 没有多少实际意义 嵌套不符合编程规范

作业

1.整理今日内容及博客
	用心去写 不要图快 更不要拷贝 文字一定要有自己的感悟
	最好用自己的话去表述
2.利用这几天的空闲时间查缺补漏 
	将之前所有的编程大题拿出来敲敲看
3.预习明日内容
	模块相关知识
posted @ 2022-07-12 21:42  逢诱  阅读(34)  评论(0)    收藏  举报