引言
前面学过可以用于for循环的数据类型有 str,list,tuple,dict,range,enumerate等;
这里先补充一下enumerate枚举的用法:,该函数可以返回索引,和容器类型中的元素:
L=['璇璇','可可','夏夏']
for index,item in enumerate(L):
print(index,item)
运行结果:
先引入一个dir函数,该函数可以返回一些数据类型对应的方法:
print(dir([]))
print(dir(()))
print(dir({}))
print(dir(range(1)))
print(dir(enumerate([])))
print(dir(str))
运行结果:
上面带有双下划线的方法又称为双下方法;
上面的这些可以都可以用for循环,来挨个取得容器类型的值,我们知道int类型是不可以使用for循环来取值的,因为int类型不可迭代:
for i in 123:
print(i)
运行结果:
iterable可迭代的:再看上面可以用于for循环的容器类型,他们都有一个类似的__iter__方法:
print("__iter__" in dir([])) #dir()函数返回的是一个list,元素是该容器类型包含的方法
print('__iter__' in dir({})) #字典有__iter__方法
print('__iter__' in dir(int))
运行结果:
其实一个规律就是凡是有__iter__方法的都可以用于for循环;
然后我们来看下[].__Iter__()是什么:
print([].__iter__()) # 查看"可迭代的iterbale".__iter__()是什么对象--迭代器(iterator)
print(dir([].__iter__())) # 返回该迭代器的方法
运行结果:
原来“可迭代的”.__iter__()返回的竟然是一个iterator(迭代器)!!
该迭代器含有的方法,我们也可以使用dir()函数来查看;
也就是[]是一个可迭代的对象(iterable) 而[].__iter__()却是一个迭代器(iterator),我们可以使用集合的差集来查看迭代器和可迭代对象之间有哪些不同:
A=set(dir([])) #集合A是可迭代对象拥有的方法
B=set(dir([].__iter__())) #集合B是迭代器拥有的方法
print(B-A) #返回的是集合B 迭代器拥有而集合A可迭代对象没有的方法
运行结果:
原来迭代器拥有一般可迭代对象没有的__next__()方法!!!
我们就是使用__next__()方法挨个从迭代器中取值的;
L=[1,2,3,4,5] #iterable 可迭代的,可用于for循环
Iterator=L.__iter__() #iterable.__iter__()就变为迭代器
print(Iterator.__next__())
print(Iterator.__next__())
print(Iterator.__next__())
print(Iterator.__next__())
print(Iterator.__next__())
运行结果:
我们接下来使用isinstance()函数可以查看两个对象是否相等:
from collections import Iterable
from collections import Iterator
print(isinstance([1,2,3],Iterator)) #看list是否是迭代器,不是的~
print(isinstance([1,2,3],Iterable)) #看list是否可迭代,当然是 都可以用于for循环
运行结果:
from collections import Iterable
from collections import Iterator
print(isinstance([1,2,3].__iter__(),Iterator)) #查看”iterable“.__iter__()之后生成是否为iterator
print(isinstance([1,2,3].__iter__(),Iterable))
运行结果:
可以用于for循环的都是可迭代对象(Iterable),都具有__iter__()方法------------可迭代协议;
含有__iter__()方法和__next__()方法的都是迭代器-------------迭代器协议;
迭代器的好处:
1.可以从容器类型中一个一个取值;
2.节省内存空间,每次循环产生一个值,每次next给一个;
talk is cheap,show me the code