迭代器
什么是迭代器
器 => 工具
迭代: 是一个重复的过程,但每次重复都是基于上一次的结果而来的
**迭代器:**就是一种不依赖于索引的取值工具
特性:
1.是一种通用的迭代取值方案
2.惰性计算,节省内存
为何要有迭代器
# 对于序列类型 str,list,tuple可以依赖索引来迭代取值
# 对于dict,set,文件 python必须为我们提供一种不依赖于索引的迭代取值的方式=》迭代器
可迭代对象:(内置有obj.__iter__()方法)
name='egon'
lis=[1,2,3]
tup=[1,2,3]
dic={'name':'egon'}
s={'a','b','c'}
f=open('file.txt','r',encoding='utf-8')
name.__iter__() #字符串类型为可迭代对象
lis.__iter__() #列表类型为可迭代对象
tup.__iter__() #元组类型为可迭代对象
dic.__iter__() #字典类型为可迭代对象
s.__iter__() #集合为可迭代对象
f.__iter__() #文件类型为可迭代对象
迭代器对象:(内置有obj.__iter__()方法也有obj.__next__()方法)
文件对象即有obj.__iter__()方法也有obj.__next__()方法属于迭代器对象
调用obj.__iter__()方法
name='egon'
name_iter=name.__iter__() #调用obj.__iter__()方法可以使可迭代对象变成迭代器对象
name._iter.__iter__()
name_iter.__next__()
总结
1、可迭代对象不一定是迭代器对象
2、迭代器对象一定是可迭代对象
3、调用obj.__iter__()方法,得到的是迭代器对象(对于迭代器对象,执行obj.__iter__()方法得到的仍然是它本身)
迭代器优缺点:
优点:
1.是一种通用的迭代取值方案
2.惰性计算,节省内存
缺点:
1.取值不如索引、key的取值方式灵活
2.取值是一次性的,只能往后取,不能预估值得个数
示例:
d={"name":"egon","age":18,"sex":"male"}
d_iter=d.__iter__() #也可以写成d_iter=iter(d)
#迭代器d_iter没有值了,就会抛出异常StopIteration
while True:
try:
data=d_iter.__next__(); #也可以写成data=next(d_iter)
print(d[data])
except StopIteration:
print("取值完毕")
break
for循环原理
dic = {"name": "egon", 'age': 18, 'gender': "male"}
# 1、dic.__iter__()得到一个迭代器对象
dic_iterator = dic.__iter__()
while True:
try:
#2、迭代器对象.__next__()拿到一个返回值,然后将该返回值赋值给res
res = dic_iterator.__next__()
print(res)
# 3、循环往复步骤2,直到抛出StopIteration异常for循环会捕捉异常然后结束循环
except StopIteration:
break
for k in dic:
print(k)
生成器
什么是生成器(就是自定义的迭代器)
但凡是函数内出现了yield关键字,调用函数将不会执行函数体代码,会得到一个返回值,该返回值就是我们自定义的迭代器,称之为生成器
def func():
print("hello1")
yield 111
print("hello2")
yield 222
print("hello3")
yield 333
# 生成器本质就是迭代器
g = func()
print(g)
res=next(g)
print(res)
# 执行结果 111
res=next(g)
print(res)
res=next(g)
print(res)
next(g)
yield功能:
#1、yield为我们提供了一种自定义迭代器的方法
#2、yield与return的区别:
#1、yield可以返回多次值
#2、函数暂停与再继续的状态是由yield帮我们保存的
示例:自定义range功能
def my_range(start,end,step=1):
while start < end:yield start
start+=step
res=my_range(1,10)
for i in res:
print(i)
生成式
l = ['alex_dsb', 'lxx_dsb', 'wxx_dsb', "xxq_dsb", 'egon']
#1、列表生成式
# 把所有小写字母全变成大写
# new_l=[name.upper() for name in l]
# print(new_l)
# 把所有的名字去掉后缀_dsb
# new_l=[name.replace('_dsb','') for name in l]
# print(new_l)
# 2、字典生成式
# keys=['name','age','gender']
# dic={key:None for key in keys}
# print(dic)
# items=[('name','egon'),('age',18),('gender','male')]
# res={k:v for k,v in items if k != 'gender'}
# print(res)
# 3、集合生成式
# keys=['name','age','gender']
# set1={key for key in keys}
# print(set1,type(set1))
生成器表达式
创建一个生成器对象有两种方式,一种是调用带yield关键字的函数,另一种就是生成器表达式,与列表生成式的语法格式相同,只需要将[]换成(),即:
(expression for item in iterable if condition)
# 生成器表达式
# g=(i for i in range(10) if i > 3)
# !!!!!!!!!!!强调!!!!!!!!!!!!!!!
# 此刻g内部一个值也没有
# print(g,type(g))
# print(g)
# print(next(g))
# print(next(g))
# print(next(g))
# print(next(g))
# print(next(g))
# print(next(g))
# print(next(g))
#统计文件中的字符个数
with open('笔记.txt',mode='rt',encoding='utf-8') as f:
# 方式一:
# res=0
# for line in f:
# res+=len(line)
# print(res)
# 方式二:
# res=sum([len(line) for line in f])
# print(res)
# 方式三 :效率最高
# res = sum((len(line) for line in f))
# 上述可以简写为如下形式
res = sum(len(line) for line in f)
print(res)