迭代器
一、定义
1.iterator.(迭代器)
2.iterable.(可迭代的)
一般来说,可以被for循环的就是可以迭代的,迭代器一定可以迭代,但是可迭代的类型不一定是迭代器。
二、说明
1.有__iter__方法,说明可迭代
def shili1(): print(dir([])) #告诉我列表拥有的所有方法 print(dir(())) print(dir('')) print(dir(range(10))) ret=set(dir([]))&set(dir(''))&set(dir({}))&set(dir(range(10))) print(ret) #有一个'__iter__'
判断一下这些类型有没__iter__方法
print('__init__' in dir(int)) print('__init__' in dir(list)) print('__init__' in dir(dict)) print('__init__' in dir(set)) print('__init__' in dir(tuple)) print('__init__' in dir(enumerate)) print('__init__' in dir(range(10))) print('__iter__' in dir(int)) #false print('__iter__' in dir(bool)) #false print('__iter__' in dir(list)) print('__iter__' in dir(dict)) print('__iter__' in dir(set)) print('__iter__' in dir(tuple)) print('__iter__' in dir(enumerate)) print('__iter__' in dir(range(10)))
2.#setstate指定从那个位置开始取(一般是从0位开始)
一个可迭代的类型执行了iter之方法后的返回值就是一个迭代器
print(set(dir([].__iter__())) - set(dir([]))) # {'__setstate__', '__next__', '__length_hint__'}
3.示例1(可迭代的不一定是迭代器,迭代器一定可迭代)
print('*'*40) l=[1,2,3] iterator=l.__iter__() print(iterator.__next__()) #l内部没有next方法,调用iter之后的返回值有next print(iterator.__next__()) #l内部没有next方法,调用iter之后的返回值有next print(iterator.__next__()) #l内部没有next方法,调用iter之后的返回值有next # print(iterator.__next__()) #报错 # 不能被循环的: not iterable(不可迭代的) -> __iter__ ->只要含有iter就可迭代且都可以被for循环 -> 可迭代协议
4.创建一个iterator
#[].__iter__()拿到一个 #可迭代协议 #在for循环时先找__iter__方法,如果没有就 #迭代器协议->内部含有next方法和__init__方法的就是迭代器 print('__iter__' in dir([].__iter__())) from collections import Iterable from collections import Iterator print(isinstance([],Iterator)) #isinstace判断是否是。迭代器,迭代类型。列表不是迭代器,但是可迭代。 print(isinstance([],Iterable)) class A: # def __init__(self):pass def __next__(self):pass #同时有next和init就是迭代器。next可以一个一个获取值 # def __iter__(self):pass #有iter就可用被迭代 a=A() print(isinstance(a,Iterable)) print(isinstance(a,Iterator)) #只要是迭代器一定可迭代,可迭代的不一定是迭代器 #可迭代的.__init__()方法可以得到一个迭代器
三、作用
使用迭代器的好处是可以节省内存空间
#用迭代器的好处:从容器类型中一个一个的取值,会把所有值都取到 # 可以节省内存空间(迭代器并不会再占用一大块内存,而是随着循环,每次生成一个,每次next给一个 #range,文件句柄 #range-> print(range(100000000)) #range(0, 100000000) 得到可迭代对象,但此时并没有生成数据 print(list(range(10000000000000))) #内存错误 print(list(range(10))) #[0,1,2,……,9] #f=open -> #没有for循环,依然可以遍历 l=[1,2,3,4] iterator=l.__iter__() while True: print(iterator.__next__())#虽然会报错,但是也一个个输出了 最后抛出StopIterator
四、总结
1.双下方法:很少直接调用的方法,一般通过其他语法触发。
2.可迭代的——可迭代协议:含有__iter__的方法(‘__iter__' in dir(数据))
3.可迭代的一定可以被for循环
4.迭代器协议:含有__iter__方法和__next__方法
5.迭代器一定可迭代,可迭代的通过调用__iter__方法可以得到一个迭代器
6.迭代器的特点:
1)方便使用,且只能取所有的数据取一次。下次重新取。
2)节省内存空间(当前和取下一个数据)