迭代器:

迭代的工具。迭代是更新换代,如你爷爷生了你爹,你爹生了你,迭代也可以说成是重复,并且但每一次的重复都是基于上一次的结果来的。如计算机中的迭代开发,就是基于软件的上一个版本更新。以下代码就不是迭代,它只是单纯的重复

 

 

可迭代对象

python中一切皆对象,对于这一切的对象中,但凡有__iter__方法的对象,都是可迭代对象。

可迭代的对象:Python内置str、list、tuple、dict、set、file都是可迭代对象。

 

 

迭代器对象

只有字符串和列表都是依赖索引取值的,而其他的可迭代对象都是无法依赖索引取值的。因此我们得找到一个方法能让其他的可迭代对象不依赖索引取值。

在找到该方法前,首先我们给出迭代器对象的概念:可迭代的对象执行__iter__方法得到的返回值。并且可迭代对象会有一个__next__方法。

一定次数后要是__next__() 调用超出上限会导致无值可取 报错StopIteration

但是在我们可以使用while循环精简下。其中使用的try...except...为异常处理模块

 

 

 

总结

迭代器对象:执行可迭代对象的__iter__方法,拿到的返回值就是迭代器对象。

特点:

内置__next__方法,执行该方法会拿到迭代器对象中的一个值
内置有__iter__方法,执行该方法会拿到迭代器本身
文件本身就是迭代器对象。
缺点:

取值麻烦,只能一个一个取,并且只能往后取,值取了就没了
无法使用len()方法获取长度

 

 

for循环原理

for循环称为迭代器循环,in后必须是可迭代的对象。
将in后面的对象调用__iter__转换成迭代器对象
调用__next__迭代取值
内部有异常捕获StopIteration,当__next__报这个错 自动结束循环

迭代器对象无论执行多少次__iter__方法得到的还是迭代器对象本身(******)

迭代器取值的特点
1.只能往后依次取 不能后退

 

特别注意类型:文件类型

文件类型本身就是一个迭代器对象

问:__iter__方法就是用来帮我们生成迭代器对象
而文件对象本身就是迭代器对象,为什么还内置有__iter__方法???
解答:for 循环 时候必须要有__iter__方法 这是必须步骤 ,所以~~~~
# f = open('xxx.txt','r',encoding='utf-8')
# iter_f = f.__iter__()
# print(iter_f.__next__())
# print(iter_f.__next__())
# print(iter_f.__next__())
# print(iter_f.__next__())
# print(iter_f.__next__())

 

生成器

yield
1.帮你提供了一种自定义生成器方式
2.会帮你将函数的运行状态暂停住
3.可以返回值

与return之间异同点
相同点:都可以返回值,并且都可以返回多个
不同点:
yield可以返回多次值,而return只能返回一次函数立即结束
yield还可以接受外部传入的值

用户自定义的迭代器,本质就是迭代器

生成器的自主yield 传值

# 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 my_range(start,end,step=1):
    while start < end:
        yield start
        start += step


for j in my_range(1,100,2):
    print(j)

 

 yield支持外界为其传参

def dog(name):
print('%s 准备开吃'%name)
while True:
food = yield
print('%s 吃了 %s'%(name,food))
# def index():
# pass

# 当函数内有yield关键字的时候,调用该函数不会执行函数体代码
# 而是将函数变成生成器
# g = dog('egon')
# g.__next__() # 必须先将代码运行至yield 才能够为其传值
# g.send('狗不理包子') # 给yield左边的变量传参 触发了__next__方法
# g.send('饺子')

 

 生成式表达式

 ()    

# 生成器不会主动执行任何一行代码
# 必须通过__next__触发代码的运行

列子如

# res = (i for i in range(1,100000000) if i != 4)  # 生成器表达式
# print(res)
# f = open('xxx.txt','r',encoding='utf-8')
# data = f.read()
# print(len(data))
# f.close()

# with open('xxx.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(g.__next__())
#     print(sum(g))

 

 

列子

生成器和迭代器的结合面试题

 

 

 还有要注意  list()  list分为3步骤  转化为 迭代器对象 然后迭代 然后添加入列表   他会执行__next__ 会把老母鸡的蛋给偷走!!!!!!!!!!!!!!!!!!!!!!!!!

 

Copyright © 2024 jinpan
Powered by .NET 9.0 on Kubernetes