可迭代对象和迭代器

可迭代对象和迭代器

一、迭代器的概念

迭代器即迭代的工具,那什么是迭代呢?
迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的结果都是下一次迭代的初始值

while True: #只是单纯地重复,因而不是迭代
    print('===>') 
    
l=[1,2,3]
count=0
while count < len(l): #迭代
    print(l[count])
    count+=1

二、可迭代对象

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

基于上一次的结果推出下一次结果

# 

# 可迭代(具有__iter__方法)对象

x = 2  # 不可迭代
# x.__iter__  # SyntaxError: invalid syntax

s = 'randysun'
s.__iter__()  # str 为可迭代对象 <str_iterator object at 0x035B4D70>

lt = [1, 2, 3]
lt.__iter__()  # list 为可迭代对象

dic = {'a': 1, "b": 2}
dic.__iter__()  # dict 为可迭代对象

tup = (1,)
tup.__iter__()  # tuple 为可迭代对象

se = {1, 2, 3}
se.__iter__()  # 可迭代对象

f = open('test.py')  
f.__iter__()  # 可迭代对象

def func():
    pass     # 不可迭代对象

# 有__iter__()方法的对象都是可迭代对象,然后除了数字类型和函数之外都是可迭代对象

可迭代的对象:Python内置str、list、tuple、dict、set、file都是可迭代对象,除了数字类型外。

s = 'randysun'

s_iter = s.__iter__()
print(s_iter.__next__())
print(s_iter.__next__())
print(s_iter.__next__())

特点:内置有__iter__方法的都叫可迭代的对象。(可以理解为可以for循环打印)

[49迭代器-装逼.jpg?x-oss-process=style/watermark

二、迭代器对象

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

迭代器对象: 具有__iter__以及__next__方法的叫做迭代器对象,只有文件是迭代器对象

s = 'randy'  # 可迭代对象,不属于迭代器对象
s.__iter__()
lt = [1, 2, 3]  # 可迭代对象,不属于迭代器对象
dic = {'a': 1, 'b': 2}  # 可迭代对象,不属于迭代器对象
tup = (1,)  # 元组只有一个元素必须得加逗号# 可迭代对象,不属于迭代器对象
se = {1, 2, 3}  # 可迭代对象,不属于迭代器对象
f = open('time.py')  # 可迭代对象,迭代器对象

# 只有文件是迭代器对象

通过迭代对象和迭代器实现遍历列表

# 不依赖索引取值 for循环原理
lt = [1, 2, 3]
lt_iter = lt.__iter__()
while True:
    try:
        print(lt_iter.__next__())
    except StopIteration:
        break

1
2
3

for i in lt:  # 可迭代对象;迭代器对象 不依赖索引取值,而是迭代取值
    print(i)
# 1. 首先使用__iter__把lt变成迭代器对象,对文文件也要使用iter方法把文件再一次iter
# 2. 然后使用__next__方法进行迭代取值
# 3. 判断StopIteration异常,遇到异常终止

三、for循环原理

for循环称为迭代器循环,in后必须是可迭代的对象。

lis = [1, 2, 3]
for i in lis:
    print(i)

1
2
3

因为迭代器使用__iter__后还是迭代器本身,因此for循环不用考虑in后的对象是可迭代对象还是迭代器对象。

由于对可迭代对象使用__iter__方法后变成一个迭代器对象,这个迭代器对象只是占用了一小块内存空间,他只有使用__next__后才会吐出一个一个值。如lis = [1,2,3,4,5,...]相当于一个一个鸡蛋,而lis = [1,2,3,4,5,...].__iter__相当于一只老母鸡,如果你需要蛋,只需要__next__即可。

Python2中

print(range(10))  # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Python3中

print(range(10))  # range(0, 10)

四、总结

  • 可迭代对象:具有__iter__方法的对象就是可迭代对象,除了数字类型和函数都是可迭代对象

  • 可迭代器对象:具有__iter__和__next__方法的都是迭代器对象,只有文件

  • 迭代器对象一定是可迭代对象,可迭代对象不一定是可迭代器对象

  • for循环 == 迭代循环

    1. 把lt(可迭代对象/迭代器对象)用__iter__方法转换成迭代器对象
    2. 使用__next__取出迭代器里的所有值
    3. 使用__next__方法取尽迭代器中的所有值,一定会报错,通过异常捕捉退出while循环
    4. 解决了不依赖索引取值
  • 优缺点

  1. 优点:

    • 提供一种统一的、不依赖于索引的迭代方式
    • 惰性计算,节省内存
  2. 缺点:

    • 无法获取长度(只有在next完毕才知道到底有几个值)
    • 一次性的,只能往后走,不能往前退,取值麻烦,只能一个一个取,并且只能往后取,值取了就没了
posted @ 2019-08-12 16:52  RandySun  阅读(231)  评论(0编辑  收藏  举报