使用dir()我们可以知道这个数据类型的内置函数有什么方法:
print(dir(int)) print(dir(bool)) print(dir([])) print(dir({})) print(dir(set))
迭代器
iterable:可迭代的
迭代就是将数据能够一个一个按顺序取出来
s = 'abc' print('__iter__' in dir(s)) #True li = [1,2] print('__iter__' in dir(li)) #True b = False print('__iter__' in dir(b)) #False i = 123 print('__iter__' in dir(i)) #False dic = {} print('__iter__' in dir(dic)) #True set1 = set() print('__iter__' in dir(set1)) #True
上面数据类型返回为真说明它是可以迭代的,反之是不可迭代的
可迭代协议:
就是内部要有一个__iter__()来满足要求
当一个具有可迭代的数据执行__iter__()它将返回一个迭代器的内存地址
print('abc'.__iter__()) #<str_iterator object at 0x005401F0>
这里的iterator的意思是迭代器
迭代器协议:
现在有一个列表我们来看看它本身和在执行了__iter__()之后的方法有什么不同:
li = [1,2,3,'a'] print(dir(li)) #['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort'] print(dir(li.__iter__())) #['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__length_hint__', '__lt__', '__ne__', '__new__', '__next__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__'] '''求两者的差集''' print(set(dir(li.__iter__())) - set(dir(li))) #{'__length_hint__', '__setstate__', '__next__'}
__length_hint__()的作用是求元素的长度
__setstate__()的作用是指定索引值从哪里开始迭代
__next__()的作用可以让值一个一个的取出在之前用到的for循环我们就是用__next__()这种方法进行取值,现在我们可以模拟for来写一个函数:
li = [1,2,3,'a'] def getItem(li): iterator = li.__iter__() while True: print(iterator.__next__()) getItem(li) # 1 # 2 # 3 # a #StopIteration 如果找不到元素就会报错
如何处理掉这个异常?
li = [1,2,3,'a'] def getItem(li): iterator = li.__iter__() while True: try: print(iterator.__next__()) except StopIteration: break getItem(li) # 1 # 2 # 3 # a
迭代器遵循迭代器协议:必须要有__iter__()和__next__()
迭代器的好处:
a.从容器类型中一个一个的取值,会把所有的值都取到
b.节省内存的空间
迭代器并不会在内存中占用一大块内存,而是随着循环每次生成一个,每一次使用__next__()来给值
range():
print(range(10000000)) #range(0, 10000000)
实际上range()在调用的时候并没有真正生成这么多的值,如果真的生成的话那么内存可能会溢出
print('__iter__' in dir(range(10))) #True print('__next__' in dir(range(10))) #False from collections import Iterable from collections import Iterator print(isinstance(range(10),Iterable)) #True 是一个可迭代对象 print(isinstance(range(10),Iterator)) #False 在执行后得到的结果并不是一个迭代器
迭代器总结:
1.可以被for循环的都是可迭代的
2.可迭代的内部都有__iter__()方法
3.只要是迭代器一定可以迭代
4.可迭代的变量.__iter__()方法可以得到一个迭代器
5.迭代器中的__next__()方法可以一个一个的获取值
6.for循环实际上就是在使用迭代器