ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

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

2021-10-04 21:34:05  阅读:145  来源: 互联网

标签:__ .__ 迭代 python 生成器 iter next print


文章目录

迭代器

分清楚迭代与循环

偏理解
知道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,生成器,iter,next,print
来源: https://blog.csdn.net/weixin_39313241/article/details/120607666

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有