迭代器 异常处理
今日内容概要
1.常见内置函数02
2.可迭代对象
3.迭代器对象
4.for循环的内部原理
5.异常处理
6.for循环的本质(自己写代码模拟)
7.生成器(自定义迭代器)
8.range功能的本质(自己写代码模拟)
今日内容详细
常见内置函数
1.help() 查看注释信息
help(len)
2.id() 返回一串相当于内存地址的数字
print(id('jason'))
3.int() 类型转换,机制转换
4.isinstance() 判断数据类型
print(type('jason') is str) #类型判断 别扭的很
不推荐
print(isinstance('jason',str)) # True
print(isinstance('jason',str)) # False
5.pow() 幂指数
print(pow(10,2))
6.round() 四舍五入
print(round(11,1)) # 第二个参数控制需要保留几位小数部分
print(round(11.29,1))
print(round(11.59,1))
7.sum()求和
print(sum([11,2,2,3,4,3,2]))
可迭代对象
1.什么叫迭代?
迭代其实就是更新换代 每一次迭代的过程都需要依赖于上一次的结果
eg:游戏的更新其实就是版本的迭代
# 单纯的循环 不是迭代
import time
while True:
print(123)
time.sleep(0,1)
# 属于迭代
n = 1
while True:
print(n)
n += 1
# 迭代取值
li = [11,22,33,44,55]
n = 0
while n < len(l1):
print(l1[n])
n += 1
2.什么是可迭代对象?
内置有__iter__方法的都可以称之为可迭代对象
1.大白话理解就是数据可以通过点的方式点出来__iter__
2.__iteer__该类代码的读法>>>:双下iter方法
3.哪些数据是可迭代对象?
依次列举并尝试调用__iter__方法即可
print(数据类型.) # 看有没有__iter__选项
列表所学数据类型
int = 11 整型不是
float = 11.11 浮点型不是
str = 'zhou' 字符串是
list = [1,2,3,4] 列表是
dict = {'name':'zhou','age':18} 字典是
tuple = (1,2,3,4) 元组是
set = {1,2,3,4,5} 集合是
bool = True 布尔值不是
f = open() 文件是 (ps:文件作为迭代对象本身也是迭代器对象)
总结:可迭代对象其实就是为了后续迭代取值做准备
提供了不依赖于索引取值的方式
迭代器对象
1.什么是迭代器对象?
可迭代器对象调用__iter__方法之后生成的结果就是迭代器对象
2.迭代器对象的特征
含有__iter__方法和__next__方法
3.如何理解迭代器对象
迭代器对象能够极大的节省存储空间
eg:类似于哆啦A梦的口袋 不用的时候就是一个口袋的面积 用的时候可以从中取出很多数据
4.迭代器对象如何取值
调用__next__方法即可 如果取完了会直接报错
ps:开辟了一种不需要索引取值的方式(for循环底层依据的就是
"""有了迭代器对象才出现了针对字典和集合的迭代取值操作"""
5.迭代器对象补充说明
有很多双下方法其实都有简便写法 但不是全部
__方法名__ 等价 方法名()
最为常见的两个是
__iter__ iter()
__next__ next()
print(s.__iter__())
= print(iter(s))
print(s.__len__())
= print(len(s))
可迭代对象调用一次__iter__方法编程迭代器对象 如果继续调用 结果还是迭代器对象本身
res = s.__iter__()
res1 = s.__iter__().__iter__().__iter__()
print(res)
print(res1) # 打印结果是一样的
迭代取值的要求
1.每次先产生一个新的迭代器对象然后取值
print(s.__iter__().__next__()) # 第一个值
print(s.__iter__().__next__()) # 第一个值
print(s.__iter__().__next__()) # 第一个值
print(s.__iter__().__next__()) # 第一个值
2.
res = s.__iter__() # 大前提条件 已经变身迭代器对象了
print(res.__iter__().__next__()) # 第一个值
print(res.__iter__().__next__()) # 第二个值
print(res.__iter__().__next__()) # 第三个值
print(res.__iter__().__next__()) # 第四个值
for循环内部原理
l1 = [1,2,3,4,5,6,7,8,9,10]
需求:不依赖于for循环 完成对列表元素的取值
res = l1.__iter__()
n = 0
while n < len(l1):
print(res.__next__())
n += 1
for循环底层原理
for 变量名 in 可迭代对象:
循环体代码
1.会将in后面的数据调用__iter__()变成迭代器对象
为什么文件对象也可以for循环 因为本身就是迭代器对象 再次调用不变
2.针对产生的迭代器对象依次调用__next__()方法迭代取值
3.当值取完之后 会自动处理报错并退出循环
res = l1.__iter__()
while True:
print(res.__next__())
异常处理
1.什么是异常?
代码运行出错之后就是异常 异常会导致程序立马停止
是我们以后在编程过程中需要极力避免的情况(异常的外号>>>:bug)
2.异常信息的组成部分
Traceback(most recent call last):
Flie "/Users/jiboyuan/PycharmProjects/day16/05 异常处理.py", line 3, in <module>
name
NameError: name 'name' is not defined
1.line 所在的这一行会提示你代码在哪一行出错了 点击前面的蓝色字体可以直接定位到出错的那一行 (ps:如果报错的信息很长 一般最后一个才是)
2.NameError错误的类型
代码的报错也可以分为很多类型
3.name 'name' is not defind
具体的报错原因(就是解决报错的答案)
3.异常的分类
1.语法异常
不被允许的 如果出现了必须立刻改正
eg;if分支结构都不会写...
2.逻辑异常
可以允许的 如果出现了尽快修改即可
eg:代码动态获取到了一个字符串类型的数据但是调用了列表的内置方法
name = 'jason'
print(name.append())
# 改bug其实就是在重新梳理你的思路,此时尽量不要打扰程序员
# 公司里写代码的流程
1.程序员写完之后自己先大致测试
2.然后交给专门的测试人员去测试
4.异常的类型(有很多 不一一列举)
print(name) # NameError 名字错误
l1 = [11,22,33]
print(l1[100]) # IndexError 索引错误
d = {'name':'jason'}
print(d['age']) # KeyError 键错误
int('jason') # ValueError 值错误
异常处理实操
"""有时候针对可能会出错的代码 也可以自己提前写好处理措施"""
正常情况下代码出错 肯定是直接导致程序停止
# 基本语法结构
try;
可能会出错的代码
except 错误的类型1 as e: # e 指代的就是错误的提示信息
针对性的处理措施
except 错误的类型2 as e: # e 指代的就是错误的提示信息
针对性的处理措施
except 错误的类型3 as e: # e 指代的就是错误的提示信息
针对性的处理措施
错误类型
很多时候可能自己都不知道会报什么类型的错误
"""万能异常:常见的报错都可以照单全收"""
try:
可能会出错的代码
except Exception as e:
统一的处理措施
#异常处理的使用尊则:
1.被检测的代码越少越好
2.能尽量少用就尽量少用
异常处理了解
1.结合else使用
当try检测的代码没有发生异常 正常运行完毕之后执行else的子代码
try:
可能会出错的代码
except Exception as e:
统一的处理措施
else:
可能会出错的代码没有出错 最后走else子代码
2.结合finally使用
无论try检测的代码是否有异常 最后都会执行finally子代码
try:
name
except Exception as e:
print(e)
finally:
无论try检测的代码是否有异常 最后都会执行finally子代码
3.全部整合到一起使用
try:
name
except Exception as e:
print(e)
else:
print('没报错 好极了')
finally:
print('管你错不错 都执行')
4.断言(了解中的了解)
name = 'jason'
assert isinsatance(name,str)
5.主动报错(需要掌握)
raise NameError
"""由于是主动报错 所以可以非常明确的知道错误的类型"""
for循环的本质
#利用while与异常捕获 实现for循环的功能
info = {'name':'jason','age':18,'pwd':123}
1.先转换成迭代器对象
res = info.__iter__()
# >>>: res = iter(info)
2.迭代取值
while True:
# print(res.__next__())
try:
print(next(res))
except StopIteration as e:
#结束while循环
break
迭代取值与索引取值的对比
1.索引取值
优势:可以反复获取相同的元素 并且没有固定的方向
劣势:只能支持有序的容器类型 无序的无法取值兼容性没有迭代取值高
2.迭代取值
优势:兼容所有的容器类型
劣势:取值的顺序永远都是从左往右 并且无法重复获取
#真正底层的迭代取值后续可能会很少用 一般都是for循环代替
"""迭代器里面的东西是固定的 没取一个就会少一个去完就完了"""