Python教程

python基础⑧-迭代器和生成器

本文主要是介绍python基础⑧-迭代器和生成器,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

文章目录

  • 迭代器
      • 分清楚迭代与循环
      • 可迭代对象
      • 迭代器
      • 文件对象也是迭代器
      • iter() next()
      • for循环原理
      • 迭代器总结
      • range函数原理
  • 生成器
      • 生成一个斐波那契数列

迭代器

分清楚迭代与循环

偏理解
知道for循环后面跟什么 *****
生成器的作业

  1. 什么是迭代器
    迭代就是更新换代
    迭代器指的是迭代取值的工具
  2. 为何要用迭代器
    器是工具
    迭代器提供了一种通用的且不依赖于索引的迭代取值方式的功能
### 迭代器的使用

#单纯的重复不是迭代
# i = 0
# while True:
#     print(i)
# 迭代:重复+每次重复都是基于上一次的结果而进行(不是是单纯的重复)
# l = ['a','b','c']
# i = 0
# while i < len(l):
#     print(l[i])
#     i += 1

# # 哪些数据类型需要这样迭代取值
# # 字符串 列表 元组 字典 集合 文件等等
# l = ['a','b','c']
# a = 'abc'
# t = ('a','b','c')
# dic = {'name':'dahai','age':18}
# i = 0
# while i < len(l):
#     print(l[i])
#     i += 1
# 所以我们需要一种不依赖索引取值的方式
# 迭代器提供了一种通用的且不依赖于索引的迭代取值方式的功能

可迭代对象

# 可迭代对象
#一 :可迭代的对象iterable:但凡内置有__iter__方法的对象都称之为可迭代的对象
# 作者是个天才,每个需要取值的都加了__iter__方法
#可迭代的对象:str,list,tuple,dict,set,文件对象
a = 1
# a.__iter__没有
b = 1.1
# b.__iter__没有
c = 'hello'
print(c.__iter__())

d = ['a', 'c']
print(d.__iter__())

e = {'x': 1}
print(e.__iter__())

g = {1, 2, 3}
# g是可迭代对象
# g.__iter__()会生成迭代器
print(g.__iter__())
f = open('b.txt', 'w')
print(f.__iter__())

在这里插入图片描述

迭代器

# 迭代器
# 执行可迭代对象下的__iter__方法,返回的值就是一个迭代器对象

dic = {'x': 1, 'y': 2, 'z': 3}
# 迭代器对象变成迭代器
iter_dic = dic.__iter__()
# iter_dic迭代器
print(iter_dic.__next__())
print(iter_dic.__next__())
print(iter_dic.__next__())


# 列表不依赖索引取值
l = [1, 2, 3]
iter_l = l.__iter__()
print(iter_l.__next__())
print(iter_l.__next__())
print(iter_l.__next__())
# #StopIteration应该被当成一种结束信号,代表迭代器取干净了
print(iter_l.__next__())

在这里插入图片描述

# 误区
l = [1, 2, 3]
print(l.__iter__().__next__())
# 基于新的迭代器对象
print(l.__iter__().__next__())
# 迭代是基于老的
iter_l = l.__iter__()
print(iter_l.__next__())
print(iter_l.__next__())

在这里插入图片描述

可迭代对象与迭代器 *****
可迭代对象
只有__iter__方法,没有__next__方法
除了文件其他容器都是可迭代对象
迭代器

  1. 既内置有__next__方法的对象,执行迭代器__next__方法可以不依赖索引取值
  2. 又内置有__iter__方法的对象,执行迭代器__iter__方法得到的仍然是迭代器本身
    迭代器一定是可迭代的对象,而可迭代的对象却不一定是迭代器对象
    可迭代的对象只需要有__iter__()
    迭代器对象 iter() next()

文件对象也是迭代器

f = open('b.txt', 'w')
print(f.__iter__())

l = [1, 2, 3]
iter_l = l.__iter__()
#  调用可迭代的对象__iter__得到的是迭代器,
# 执行迭代器__iter__方法得到的仍然是迭代器本身,那么有什么用
# 为了for循环
print(iter_l is iter_l.__iter__().__iter__().__iter__())

在这里插入图片描述

iter() next()

#   iter()   next()
dic = {'x': 1, 'y': 2, 'z': 3}
#
iter_dic = iter(dic)
print(iter_dic)
# 底层 print(dic.__iter__())

print(next(iter_dic))
# 底层 print(iter_dic.__next__())

在这里插入图片描述

# 解决迭代器报错

# 异常捕获
dic = {'x': 1, 'y': 2, 'z': 3}
#
iter_dic = iter(dic)
# 异常捕获
while True:
    try:
        print(next(iter_dic))
    except StopIteration:
        break

print('=========')
# # 同一个迭代器只能完整地取完一次值

while True:
    try:
        print(next(iter_dic))
    except StopIteration:
        break

在这里插入图片描述

for循环原理

# 有没有一种好的方法自己把
# 1.可迭代对象变成迭代器对象
# 2.能够自己获取迭代器对象next的值
# 3.next最后不报错
#for本质应该称之为迭代器循环  *****
# 那么以后大家知道for循环后面可以跟迭代器和可迭代对象
#底层工作原理
#1. 先调用in后面那个对象的__iter__方法,将其变成一个迭代器
    # 如果是个迭代器__iter__可以变成迭代器
    # 如果是个可迭代对象__iter__可以变成迭代器
#2. 调用next(迭代器),将得到的返回值赋值给变量名  k
#3. 循环往复直到next(迭代器)抛出异常,for会自动捕捉异常StopIteration然后结束循环
# 可迭代对象包含迭代器对象
# 文件对象是迭代器,那么for循环也会自动调用__iter__,那么还是一个迭代器
# 那么for循环的机制就可以通用,这就是为什么迭代器对象里面也有一个__iter__的方法的原因
dic = {'x': 1, 'y': 2, 'z': 3}
for k in dic:
    print(k)
# 为什么下一次又可以
# 因为又做了上面三件事 又变成了一个新的dic迭代器
for k in dic:
    print(k)

在这里插入图片描述

迭代器总结

#迭代器总结
# 优点:
#     1. 提供一种通用的且不依赖于索引的迭代取值方式
#     2. 同一时刻在内存中只存在一个值,更节省内存

# 缺点:
#     1. 取值不如按照索引的方式灵活,(不能取指定的某一个值,而且只能往后取)
#     2. 无法预测迭代器的长度

range函数原理

obj_iter = range(1, 10)
# obj_iter可迭代对象
print(obj_iter)
obj_next = iter(obj_iter)
print(obj_next.__next__())
print(obj_next.__next__())
print(obj_next.__next__())
print('迭代器的for循环')  # 1 开 1     4
for i in obj_next:
    print(i)
print('可迭代对象for循环')
print('=============')
for i in obj_iter:
    print(i)

在这里插入图片描述

生成器

大前提:生成器就是一种自定义的迭代器,本质就是迭代器
但凡函数内包含yield关键字,调用函数不会执行函数体代码,
会得到一个返回值,该返回值就是生成器对象

def func():
    print('====1')
    yield 1
    print('====2')
    yield 2
    print('====3')
    yield 3

g = func()
print(g)
print(g is g.__iter__().__iter__())
g.__next__()
res1 = next(g)
#  #会触发函数的执行,直到碰到一个yield停下来,并且将yield后的值当作本次next的结果返回
print(res1)
res2 = next(g)
print(res2)
res3 = next(g)
print(res3)

# 生成器一般for连用
# for i in g:
#     print(i)
# 总结yield:只能在函数内使用
#1. yield提供了一种自定义迭代器的解决方案
#2. yield可以保存函数的暂停的状态
#3. yield对比return
#   1. 相同点:都可以返回值,值的类型与个数都没有限制
#   2. 不同点:yield可以返回多次值,而return只能返回一次值函数就结束了

在这里插入图片描述

生成一个斐波那契数列

'''
定义一个生成器,这个生成器可以生成10位斐波拉契数列,得到斐波拉契数列
# (斐波那契数列:数列中每一个数的值都等于前两个数相加的值 [1, 1, 2, 3, 5, 8, 13, 21, 34, 55.........])
'''
def run(n):
    i, a, b = 0, 1, 1
    while i < n:
        yield a
        a, b = b, a + b
        i += 1


for i in run(10):
    print(i)

在这里插入图片描述

这篇关于python基础⑧-迭代器和生成器的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!