A-Z 65 -90

a-z 97-122

迭代取值 = for循环取值(每次取值都依赖于上一次取值)

python基础之异常处理、生成器对象、生成器表达式

一、异常处理语法结构

1.异常的常见类型

1.语法错误
  if 后面没东西
  SyntaxError:invalid syntax
2.名字错误
  name 没有赋值
  NameError
3.索引错误
  l1 = [1,3,4]
  l1[100]
  IndexError
4.字典关键字错误
  d1={'name':'duo'}
  d1['age']
  KeyError关键字错误
5.缩进错误
  IndentationError缩进错误: unexpected indent

2.异常处理语法结构

1.语法结构
try:
    待监测的代码(可能会出错的代码) # 监测代码会占用一定的资源
except 错误类型:
    针对上述错误类型制定的方案
    
# 举例
try: 
    name
except NameError:
    print('名字没被定义')
    
2.查看错误的类型
try:
    待监测的代码(可能会出错的代码)
except 错误类型 as e:  # e 系统提示的错误信息
    针对上述错误类型制定的方案
    print(e)  # 会打印提示的错误信息
    
3.针对不同的错误类型制定不同的解决方案**
# 把能想到的错误类型都写上
try:
    待监测的代码(可能会出错的代码)
except 错误类型1 as e:  # e 系统提示的错误信息
    针对上述错误类型1制定的方案
    
except 错误类型2 as e:  # e 系统提示的错误信息
    针对上述错误类型2制定的方案

except 错误类型3 as e:  # e 系统提示的错误信息
    针对上述错误类型3制定的方案

    
4.万能异常**
try:
    待监测的代码(可能会出错的代码) 
except Exception as e:  # e 系统提示的错误信息
# 或者 except BaseException as e:  
# Exception 等价于 BaseException
    print(e)
    针对上述不同的错误类型统一处理
    
5.try 结合 else使用:
try:
    待监测的代码(可能会出错的代码)
except Exception as e:  # e 系统提示的错误信息
    print(e)
    针对上述不同的错误类型统一处理
else:
    try的子代码正常运行结束没有任何报错后,再执行else子代码

6.try 结合 finally使用

finally:
    无论try的子代码是否报错,最后都要执行finally子代码
    

3.异常处理补充

1.assert 断言
assert 提前判断是否符合要求,是的话就继续往下走,不是的话就会报错


# 判断是否是字符串
name = 'duo'
assert isinstance(name, int)
print('is str')

name = 'duo'
assert isinstance(name, str)
print('is str')


2.raise 主动抛异常
关键字 raise

name = 'duo'
if name == 'duo':
    raise Exception('主动报错')
else:
    print('代码继续走')

4.异常处理实战应用


1.异常处理能尽量少用(try子代码监测会占用一定的资源)
2.被try监测的代码越少越好
3.当代码中可能会出现一些无法控制的情况报错 才应该考虑使用
# 举例:编写网络爬虫程序请求数据 断网

课堂练习:

   使用while 循环+ 异常处理+迭代器对象,完成for循环迭代取值的功能
# for循环底层代码

l1 = [11, 22, 33, 44, 55, 66, 77, 88, 99]
res = l1.__iter__()
while True:
    try:
        res1 = res.__next__()
        print(res1)
    except StopIteration as e:
        break
        
# 详细版        
l1 = [11, 22, 33, 44, 55, 66, 77, 88, 99]
# 1 先将l1调用 __iter__方法变为迭代器对象
# 1.1 迭代器对象需要用变量名接收
res = l1.__iter__()
# 2 while 循环获取l1中的值
while True:
    # 3 __next__方法取值没有会报错,再加上异常处理
    try:
        print(res.__next__())
    # 4 迭代取不到值就是StopIteration,可以将万能异常Exception表达更清楚
    except StopIteration as e:
        break        

三、生成器对象

1.生成器对象的本质

1.本质
  还是内置有__iter__和 __next__的迭代器对象
  
  生成器对象定义六一个__next__方法,它要么返回迭代中的下一项,要么引发一个特殊的StopIteration异常来终止迭代,一个可迭代对象的迭代器用iter内置函数来接收值。

image-20221017151313073

2.语法


2. 迭代器对象 和 生成器对象的 区别

  1)迭代器对象是解释器自动提供的
       数据类型、文件对象 >>>: 迭代器对象 
  2)生成器对象是程序员自己写出来的
       代码、关键字 >>>: 迭代器对象(生成器)
 3.创建生成器的语法(生成器函数)

函数体代码中加一个 yield关键字  # 则可以用 __next__方法

# 举例
def my_iter():
    print('duoduodudoudouodo')
    yield

'''
1 函数体代码中如果有yield关键字,
那么函数名加括号并不会执行函数体代码
会生成一个生成器对象
'''
my_iter()
res = my_iter()
'''
2 使用加括号之后的就能够调用__next__才会执行函数体代码

'''
res.__next__()
'''
3 每次执行完__next__代码都会停在yield位置,
下次基于该位置继续往下找第二个yield
'''
res.__next__()  # StopIteration

def my_iter():
    print('duoduodudoudouodo')
    yield 111
    print('2222')
    yield 222
    print('3333')
    yield 333
    print('4444')
    yield 444
    
res = my_iter()
r1 = res.__next__()  # 不赋值给变量名的话,只返回为一个地址
print(r1)
res.__next__()
res.__next__()
res.__next__()
'''
4 yield有点类似于return 可以返回返回值
'''  

image-20221017110338157

四、用生成器对象实现range方法

  自定义生成器对标range功能(一个参数 两个参数 三个参数 利用迭代器对象)
  
1.先写两个参数的
def my_range(start_num, end_num):
    while start_num < end_num:
        yield start_num
        start_num += 1
# 方法1
for i in my_range(1, 10):
    print(i)
    
# 方法2
res = my_range(1, 10).__iter__()
while True:
    try:
        print(res.__next__())
    except StopIteration:
        break
        
        
2.增加参数和判断条件,实现range有一个参数和三个参数的功能

def my_range(start_num, end_num=None, step=1):
    # 判断end_num是否有值,没有值说明用户只给了一个值,起始数字应该是0,终止位置应该是传的值
    if not end_num:
        end_num = start_num
        start_num = 0
    while start_num < end_num:
        yield start_num
        # step 默认为1 ,用step代替加的数字,则可以控制步长
        start_num += step

for i in my_range(1, 10, 2):
    print(i)

image-20221017113321417

五、yield冷门用法

1. send方法 :send方法是生成一些列结果的下一个元素

通过调用send方法,将send的参数发送给 调用了next__方法产生了的生成器,并且生成器中的yield表达式返回了发送给send函数的值

def eat(name,food =None):
    print(f'{name}准备吃饭')
    while True:
        food = yield
        print(f'{name}准备吃{food}')
res = eat('jason')
res.__next__()
res.send('汉堡')  # 1 将括号内的数据传递给yield前面的变量名 2 再自动调用__next__
# jason准备吃饭
# jason准备吃汉堡

# 之后再次调用__next__方法,yield则返回None
res.__next__()  # jason准备吃None 

image-20221017120731196

六、生成器表达式

1.生成器表达式

1.什么是生成器表达式:就是生成器的简化写法,结果是生成器对象
'''
生成器里面的代码,只有 
1 调用__next__方法  
2 for循环的时候才会执行
'''

l1 = (i ** 2 for i in range(100))  # 1 生成器表达式
print(l1)  # <generator object <genexpr> at 0x100776900>

for i in l1:  # 2 for循环的时候才会执行
    print(i)
   

2.生成器表达式是一个能够将函数的灵活性与推导语法的简洁性结合到一起的工具
# 举例
def ups(line):
    for i in line.split(','):
        yield i.upper()

# 生成器关键字加括号(),激活生成器
res = tuple(ups('aaa,bbb,ccc'))
print(res)  # AAA BBB CCC

d1 = {i: j for (i, j) in enumerate(ups('aaa,bbb,ccc'))}
print(d1)   

2.生成器表达式面试题

# 大致知道流程即可

def add(n, i):  # 定义一个普通函数:返回两个数的和(求和函数)
    return n + i
def test():  # 生成器 函数
    for i in range(4):
        yield i
g = test()  # 激活生成器
for n in [1, 10]:
    g = (add(n, i) for i in g)
    """
    第一次for循环
        g = (add(n, i) for i in g)
    第二次for循环
        g = (add(10, i) for i in (add(10, i) for i in g))
    """
res = list(g)
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]

image-20221017122523789
image-20221017160549078
image-20221017160713217

原文地址:http://www.cnblogs.com/DuoDuosg/p/16799623.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性