迭代器
什么是迭代器?
迭代:更新换代(重复)的过程,每次的迭代都必须基于上一次的结果
迭代器:迭代取值的工具
为什么要用?
迭代器给你提供了一种不依赖与索引取值的方式
n = 0 while True: print(n) #这就是不算是迭代器,只是简单的重复 l = [1,2,3,4] s = 'hello' n = 0 while n < len(s): print(n) n+=1 #重复+每次迭代都是基于上一次的结果而来的
需要迭代取值的数据类型:
字符串
列表
元组
字典
集合
可迭代对象:只要内置有__iter__方法的都叫做可迭代对象
基本数据类型中是可迭代的对象有:
str list tuple set dict
文件对象(执行内置的__iter__之后还是本身 没有任何变化):文件对象本身就是迭代器对象
s = 'hello' l = [1,2,34,] t = (1,2,34) s1 = {1,2,3,4} d = {'name':'jason'} f1 = open('xxx.txt','w',encoding='utf-8') res = s.__iter__() # res = iter(s) print(s.__len__()) # 简化成了len(s) res1 = l.__iter__() # res1 = iter(l) res2 = f1.__iter__() # res2 = iter(f1) print(res,res1,res2) print(f1)
可迭代对象执行内置的__iter__方法得到就是该对象的迭代器对象
迭代器的取值
迭代器对象:
1.内置有__iter__方法
2.内置有__next__方法
ps:迭代器一定是可迭代对象,而可迭代对象不一定是迭代器对象
l = [1,2,3,4] iter_l = l.__iter__() #生成一个迭代器对象 #迭代器取值调用__next__ print(iter_l.__next__()) print(iter_l.__next__()) print(iter_l.__next__()) print(iter_l.__next__()) print(iter_l.__next__()) #如果取完了 直接报错 d = {'name':'yzy','sex':'male'} #将可迭代对象d转换成迭代器对象 iter_d = d.__iter__() #迭代器对象的取值必须用__next__ print(iter_d.__next__()) print(iter_d.__next__()) print(iter_d.__next__()) #取完了 报错StopIteration
迭代器对象无论执行多少次__iter__方法得到的还是迭代器对象本事(******)
d = {'name':'jason','password':'123','hobby':'泡m'} iter_d = d.__iter__() #异常处理 while True: try: print(iter.d__next__()) except StopIteration: print('no') break
d = {'name':'jason','password':'123','hobby':'泡m'} iter_d = d.__iter__() #异常处理 while True: try: print(iter.d__next__()) except StopIteration: print('no') break
迭代器取值的特点:
只能往后依次取,不能后退
Ps:可迭代对象执行内置的__iter__方法得到的就是该对象的迭代器对象
d = {'name':'jason','password':'123','hobby':'泡m'}
for i in d:
print(i)
#for循坏后面的in关键 跟的是一个可迭代对象
for循坏内部的本质
1.将in后面的对象调用__iter__转换成迭代器对象
2.调用__next__迭代取值
3.内部有异常捕获StopIteration,当__next__报这个错 自动结束循坏
可迭代对象:内置有__iter__方法
迭代器对象:既内置有__iter__也有内置__next__方法
迭代取值:
优点:
1.不依赖与索引取值
2.内存中永远只占一份空间,不会导致内存溢出
缺点:
1.不能够获取指定的元素
2.取完之后会报StopIteration错
生成器
用户自定义的迭代器,本质上就是迭代器
def func():
print('first')
yield 666 # 函数内如果有yield关键字,那么加括号执行函数的时候并不会触发函数体代码的运行
print('second')
yield 777
print('third')
yield 888
print('forth')
yield
yield
#yield 后面跟的值就是调用迭代器__next__方法你能得到的值
#yield既可以返回一个值也可以返回多个值,并且多个值也是按照元组的形式返回
g = func()#生成器初始化:将函数变成迭代器
print(g)
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())
#yield支持外界为其传参
def dog(name):
print('%s 准备开吃'%name)
while True:
food = yield
print('%s 吃了 %s'%(name,food))
当函数内有yield关键字的时候,调用该函数不会执行函数体代码
而是将函数变成生成器
g = dog('yyy')
g.__next__() # 必须先将代码运行至yield 才能够为其传值
g.send('apple') # 给yield左边的变量传参 触发了__next__方法
yield
1.帮你提供了一种自定义生成器方式
2.会帮你将函数的运行状态暂停
3.可以返回值
与return之间的异同点:
相同点:都可以返回值,都可以返回多个
不同点:
yield可以返回多次值,而return只能返回一次函数立即结束
yield还可以接受外部传入的值
生成器表达式
res = (i for i in range(1,100) if i != 4) #生成器表达式 #生成器不会主动执行任何一行代码,必须通过__next__触发代码的运行 print(res.__next__()) print(res.__next__()) print(res.__next__()) print(res.__next__())
with open('name.txt','r',encoding='utf-8')as f: n = 0 for line in f: n += len(line) print(n) g = (len(line) for line in f) print(g.__next__()) print(g.__next__()) print(g.__next__()) print(sum(g))
常用的内置方法
abs()#求绝对值
abs(-1)
print(bin(10)) #2进制 print(oct(10)) #8进制 print(hex(10)) #16进制 print(int('0b1010',2) #将2进制转换成10进制 callable()#判断是否可调用 print(chr(97))#将数字转换成ascii码表对应的字符 print(ord('a')) #将字符按照ascii表转成对应的数字 dir 获取当前对象名称空间里面的名字 l = [1,2,3] print(dir(l)) divmod 分页器 print(divmod(100,10)) total_num,more = divmod(900,11) if more: total_num += 1 print('总页数:',total_num) enumerate 枚举 l = ['a','b'] for i,j in enumerate(l,1): print(i,j) eval exec s = """ print('hello baby') x = 1 y = 2 print(x+y) """ eval(s) exec(s) #eval 不支持逻辑代码,只支持一些简单的python代码 isinstance 判断对象是否属于某个数据类型 n = 1 print(inistance(n,int)) pow print(pow(2,3)) #8 round print(round(3.4)) # 3 print(round(3.6)) #4
面向过程编程:就类似与设计一条流水线
好处:
将复杂的问题流程化 从而简单化
坏处:
可扩展性较差 一旦需要修改 整体都会受到影响