标签:__ .__ 迭代 对象 res 生成器 next print
可迭代对象
# 迭代
迭代就是更新换代 每次都是基于上次结果(游戏版本更新)
内置有__iter__方法的都称之为可迭代对象
'''迭代其实给我们提供了一种不依赖索引取值的方式'''
# 可迭代对象
内置有__iter__方法的都称之为可迭代对象
内置的意思是可以通过点的方式直接查看到的
"""
针对双下滑线开头 双下滑线结尾的方法 最为专业标准的读法为
双下方法名
面向对象的时候为了与隐藏变量区分开
"""
# n = 1
# while True:
# n+=1
# print(n)
# l = [11,22,33,44,55,66]
# n = 0
# while n < len(l):
# print(l[n])
# n += 1
i = 12 # 没有
f = 11.11 # 没有
s = 'jason' # 有
l = [111,22,33,4] # 有
d = {'username':'jason','pwd':123} # 有
t = (11,22,33) # 有
se = {11,22,33} # 有
b = True # 没有
# file = open(r'a.txt','w',encoding='utf8')
"""
含有__iter__的有
字符串 列表 字典 元组 集合 文件对象
上述通常为可迭代对象
"""
print(d)
print(d.__iter__()) # 等价于调用了一个内置方法 d.get()
print(iter(d))
print(d.__len__())
print(len(d))
"""
可迭代对象调用__iter__方法会变成迭代器对象(老母猪)
__iter__方法在调用的时候还有一个简便的写法iter()
一般情况下所有的双下方法都会有一个与之对应的简化版本 方法名()
"""
迭代器对象
"""
迭代器对象
即含有__iter__方法 又含有__next__方法
迭代器对象也是可迭代对象
但是可迭代对象不一定是迭代器对象
文件对象本身即是可迭代对象又是迭代器对象
迭代器对象无论执行多少次__iter__方法 还是迭代器对象(本身)
迭代器给我们提供了不依赖于索引取值的方式
"""
i = 12 # 没有
f = 11.11 # 没有
s = 'jason' # 有
l = [111,222,333,444] # 有
d = {'username':'jason','pwd':123} # 有
t = (11,22,33) # 有
se = {11,22,33} # 有
b = True # 没有
file = open(r'a.txt','w',encoding='utf8')
# res = s.__iter__() # 转成迭代器对象
# print(res.__next__()) # 迭代器对象执行__next__方法其实就是在迭代取值(for循环)
# print(res.__next__())
# print(res.__next__())
# print(res.__next__())
# print(res.__next__())
# res = d.__iter__() # 转成迭代器对象
# print(res.__next__()) # 迭代器对象执行__next__方法其实就是在迭代取值(for循环)
# print(res.__next__())
# print(res.__next__()) # 取完元素之后再取会"报错"
# 易错
# print(d.__iter__().__next__()) # username
# print(d.__iter__().__next__()) # username
# print(d.__iter__().__next__()) # username
# print(d.__iter__().__next__()) # username
# print(d.__iter__().__next__()) # username
# print(d.__iter__().__next__()) # username
for循环的本质
l1 = [1,2,3,4,5,6,7,8,9,11,22,33,44,55]
# 循环打印出列表中每个元素 但是不能使用for循环 __next__() next()
# 1.先将列表转为迭代器对象
# res = l1.__iter__()
# # 2.循环执行__next__取值
# while True:
# print(res.__next__())
# for i in l1:
# print(i)
"""
for循环内部原理
1.将关键字in后面的数据先调用__iter__方法转为迭代器对象
2.循环执行__next__方法
3.取完之后__next__会报错 但是for循环会自动捕获该错误并处理
res = 数据.__iter__()
while True:
检测代码是否会报错
res.__next__()
如果报错了则自动处理掉并结束while循环
"""
异常捕获
# 什么是异常
代码运行出错会导致异常 异常发生后如果没有解决方案则会到底整个程序结束
# 异常三个重要组成部分
1.traceback
翻到最下面从下往上的第一个蓝色字体鼠标左键点击即可跳转到错误的代码所在的行
2.XXXError
错误的类型
3.错误类型冒号后面的内容
错误的详细原因(很重要 仔细看完之后可能就会找到解决的方法)
# 错误的种类
1.语法错误
不被允许的 出现了应该立刻修改!!!
2.逻辑错误
可以被允许的 出现了之后尽快修改即可
'''修改逻辑错误的过程其实就是在从头到尾理清思路的过程'''
# print(idna) # NameError
# l = [11,22,33]
# print(l[100]) # IndexError
# d = {'username':'jason'}
# print(d['xxx']) # KeyError
# int('abc') # ValueError
"""
基本语法结构
try:
有可能会出错的代码
except 错误类型 as e:
出错之后对应的处理机制(e是错误的详细信息)
except 错误类型 as e:
出错之后对应的处理机制(e是错误的详细信息)
except 错误类型 as e:
出错之后对应的处理机制(e是错误的详细信息)
"""
# try:
# int('abc')
# except NameError as e:
# print('变量名name不存在',e)
# except ValueError:
# print('值不是纯数字')
# 万能异常
try:
# int('abc')
print(name)
# l = [11]
# l[100]
except Exception:
print('你来啥都行 无所谓')
try:
被监测的代码
except 错误类型 as e:
...
else:
被监测的代码不报错的时候执行
finally:
无论是否报错最终都会执行
# 断言(了解)
name = 'jason'
assert isinstance(name,str)
# 主动报异常
raise 错误类型
"""
异常捕获句式和万能异常
1.有可能会出现错误的代码才需要被监测
2.被监测的代码一定要越少越好
3.异常捕获使用频率越低越好
"""
迭代取值与索引取值对比
"""
迭代取值
优点:
1.不依赖于索引的一种通用取值方式
缺点:
1.取值的顺序永远都是固定的从左往右 无法重复获取
索引取值
缺点:
1.需要提供有序容器类型才可取值(不是一种通用的方式)
优点:
1.可以重复取值
"""
生成器对象
"""
生成器其实就是自定义迭代器
"""
# 定义阶段就是一个普通函数
def my_ge():
print('first')
yield 123,222,333
print('second')
# yield 456,444,555
"""
当函数体内含有yield关键字 那么在第一次调用函数的时候
并不会执行函数体代码 而是将函数变成了生成器(迭代器)
"""
# 调用函数:不执行函数体代码 而是转换为生成器(迭代器)
# res = my_ge()
# ret = res.__next__() # 每执行一个__next__代码往下运行到yield停止 返回后面的数据
# print(ret)
# ret = res.__next__() # 再次执行__next__接着上次停止的地方继续往后 遇到yield再停止
# print(ret)
自定义range功能
def my_range(start, stop=None, step=1):
if not stop:
stop = start
start = 0
while start < stop:
yield start
start += step
# res = my_range(10)
# for i in res:
# print(i)
# res = my_range(1,10)
# for i in res:
# print(i)
res = my_range(1,10,3)
for i in res:
print(i)
yield传值(了解)
def eat(name):
print('%s 准备干饭!!!'%name)
while True:
food = yield
print('%s 正在吃 %s' % (name, food))
res = eat('jason') # 并不会执行代码 而是转换成生成器
res.__next__()
res.send('肉包子')
res.send('盖浇饭')
yield与return对比
yield
1.可以返回值(支持多个并且组织成元组)
2.函数体代码遇到yield不会结束而是"停住"
3.yield可以将函数变成生成器 并且还支持外界传值
return
1.可以返回值(支持多个并且组织成元组)
2.函数体代码遇到return直接结束
生成器表达式
l = [11, 22, 33, 44, 55, 66, 77, 88, 99]
# res = [i+1 for i in l if i!=44]
# print(res)
# res1 = (i+1 for i in l if i!=44)
"""
生成器表达式内部的代码只有在迭代取值的时候才会执行
"""
# print(res1.__next__())
# print(res1.__next__())
# print(res1.__next__())
"""
迭代器对象 生成器对象 我们都可以看成是"工厂"
只有当我们所要数据的时候工厂才会加工出"数据"
上述方式就是为了节省空间
"""
# 求和
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]
标签:__,.__,迭代,对象,res,生成器,next,print 来源: https://www.cnblogs.com/ouyangzhen/p/15588924.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。