异常捕获、生成器对象以及yield用法

异常捕获

# 1.如何理解异常
    程序在运行的过程中如果出现了异常会导致整个程序的结束
    异常就是我们口中的'bug'

# 2.异常的结构
''' Traceback (most recent call last):
  File "/Users/xunfei/PycharmProjects/day21/异常捕获.py", line 1, in <module>
    name
NameError: name 'name' is not defined '''

# 2.1.关键字line所在行
    精准提示你哪一行代码出错
# 2.2.最后一行冒号左侧
    是异常的类型
# 2.3.最后一行冒号右侧
    错误的具体原因(关键)
	
# 3.异常的分类
    3.1. 语法错误:不允许出现,一旦出现请立刻修改
    3.2逻辑错误:允许出现,发现后修改

# ps: 写代码时,具体功能实现后先大致测一下,然后在提交

异常捕获实战演练

# 1.什么时候才可能会需要自己写代码处理异常
    当代码不确定什么时候会报错的情况下需要自己写代码处理异常
	比如编写网络爬虫访问网页数据并处理,有可能出现断网数据没有处理不了
	
# 2.异常捕获的使用相当于是提前预测可能出现的问题,并给出处理措施

# 3.异常捕获的代码实现
# 3.1基本语法结构
	try:
		name
		# l1 = [1,2]
		# l1[100] =100
	except NameError as e:
		print(e)  # name 'name' is not defined
	except IndexError as e:
		print(e)  # list assignment index out of range
	...
	
# 3.2万能异常(笼统处理方式)
	try:
		# name
		d= {'name':'jason'}
		d['pwd']
		# 123+'hello'
	except Exception as e:  # 万能异常处理方式1
		print(e)
	except BaseException as e: # 万能异常处理方式2
		print(e)
		
# 4.异常捕获其他操作补充
# 4.1 else与finally
	try:
		# name
		age = 18
	except Exception as e:
		print('程序出错了')
	else:
		print('程序如果不出错,会执行else代码')
	finally:
		print('不管程序出不出错,都会执行finally代码')
		
# 4.2 断言
	name = 'jason'  # 通过一系列的手段获取来的数据
	assert isinstance(name,str)  # 断言数据属于什么类型,如果不对就直接报错,对则正常执行下面代码
	print('针对name数据使用字符串相关操作')
# 4.3 主动抛异常
	name = input('username>>>:').strip()
	if name == 'jason':
		# raise NameError('jason来了,给他来个异常')
		raise Exception('反正就是有异常')
	else:
		print('不是jason,正常执行程序')

# 5.强调
    1.异常捕获能尽量少用就尽量少用
    2.被try监测的代码能尽量少就尽量少

异常捕获练习

# 1.for循环内部的本质
	l1 = [11,22,33,44,55,66,77]
	res= l1.__iter__()
	while True:
		try:
			print(res.__next__())
		except Exception  as e :
			break

生成器对象

# 1.本质: 就是迭代器对象
    只不过迭代器是解释器提供给我们的(现成的)
    生成器是我们自己定义出来的
	__iter__和__next__
	
# 2.目的:学习生成器对象的目的是为了优化代码
    一种不依赖于索引取值的通用方式
        可以节省数据类型的内存占用空间(主要)
		
# 3.实现

def index():
    print('hello,python!')
    yield 11,22,33
    print('hello,mysql!')
    yield 44
    print('hello,redis!')
    yield 55

"""
当函数体代码中有yield关键字
那么函数名第一次加括号调用不会执行函数代码
而是普通的函数变成了迭代器对象(生成器)返回值
"""
print(index)  # <function index at 0x1061cd430>
res = index()  # <generator object index at 0x10626e660>
print(res)
"""
yield可以在函数体代码中出现多次
每次调用__next__方法都会从上往下执行直到yield代码停留
"""
res.__next__()
res.__next__()
res.__next__()

"""
yield后面如果有数据值,则会像return一样返回出去
如果有多个数据值逗号隔开,那么也会自动组织成元组返回
"""

# 小练习
# 编写生成器  实现range方法的功能
"""简单实现大概功能"""
def my_range(start,end=None,step=1):
    if not end:
        end = start
        start =0
    while start< end:
        yield start
        start +=step

for i in my_range(2,15,2):
    print(i)

yield其他用法

def index(name,food=None):
    print(f'{name}准备干午饭')
    while True:
        food = yield
        print(f'{name}正在吃{food}')
res = index('jason')
print(res)
res.__next__() # jason准备干午饭
res.__next__()  # jason正在吃None

""" send() 方法会自动传值并自动调用__next__方法"""
res.send('韭菜')  # jason正在吃韭菜
res.send('生蚝')  # jason正在吃生蚝
res.send('腰子')  # jason正在吃腰子

生成器表达式

l1 = [i **2 for i in range(10) if i >3]
print(l1)  # [16, 25, 36, 49, 64, 81]
l2 = (i **2 for i in range(10) if i >3)
print(l2)  # <generator object <genexpr> at 0x105997660>
print(list(l2))  # [16, 25, 36, 49, 64, 81]
posted @ 2022-07-12 15:52  荀飞  阅读(57)  评论(0编辑  收藏  举报