迭代器
可迭代对象
内部含有__iter__方法的就是可迭代对象,遵循可迭代协议。
可迭代协议:
假如我们自己写了一个数据类型,希望这个数据类型里的东西也可以使用for被一个一个的取出来,那我们就必须满足for的要求。这个要求就叫做“协议”。
可以被迭代要满足的要求就叫做可迭代协议。可迭代协议的定义非常简单,就是内部实现了__iter__方法。
dir:查看对象所有方法
# print(dir('123')) # '__iter__'----------------------------True
# print('__iter__' in dir([1, 2, 3]))---------------------------True
# print('__iter__' in dir({'name':'alex'}))---------------------------True
# print('__iter__' in dir({'name'}))---------------------------True
# print('__iter__' in dir((1, 2, 3)))---------------------------True
# print('__iter__' in dir(1)) --------------------------- False
# print('__iter__' in dir(True))--------------------------- False
什么是迭代器?
可迭代对象通过__iter__()可以转换成迭代器,满足迭代器协议。
内部含有__iter__且__next__方法的就是迭代器。
# l = [1, 2, 3]
# l_obj = l.__iter__()
# print(l_obj)
迭代器的取值两种方法:
l = [1, 2, 3] l_obj = l.__iter__() print(l_obj)------------------<list_iterator object at 0x000002B84DE73748> 方法一:__next__() print(l_obj.__next__())-------------1 print(l_obj.__next__())-------------2 print(l_obj.__next__())-------------3 方法二 for循环 for i in l_obj: print(i) print('__next__' in dir(l_obj)) -------------1 2 3 True
第二种判断方法:
from collections import Iterable
from collections import Iterator
print(isinstance('123', Iterable))
print(isinstance('123', Iterator))
迭代器:
1,节省内存
2,满足惰性机制
3,取值过程单向不可逆(一条路走到黑)
迭代器遵循迭代器协议:必须拥有__iter__方法和__next__方法。
for循环,能遍历一个可迭代对象,他的内部到底进行了什么?
- 将可迭代对象转化成迭代器。(可迭代对象.__iter__())
- 内部使用__next__方法,一个一个取值。
- 加了try异常处理功能,取值到底后自动停止,防止报错。
用while循环模拟for循环:
l = [1, 2, 3, 4, 5] l_obj = l.__iter__() while True: try: print(l_obj.__next__()) except Exception: break ------------1 2 3 4 5
生成器
生成器本质也是迭代器,生成器是自己用python构建的迭代器
1,通过生成器函数构建
2,通过生成器推导式构建。
def func1(): print(666) return 222 ret = func1() print(ret)----------------666 222 def func1(): print(11) print(333) yield 222 print(666) yield 777 g_obj = func1() # 生成器对象 generator object print(g_obj.__next__()) print(g_obj.__next__()) --------------------------11 333 222 666 777
def cloth1(): for i in range(1,10001): print('衣服%s' % i) cloth1() 打印''衣服+序号'’直到----------衣服10000 def cloth2(): for i in range(1,10001): yield '衣服%s' % i g = cloth2() for i in range(1,51): print(g.__next__()) for i in range(1, 151): print(g.__next__()) 打印''衣服+序号'' 一直打印到----衣服200
next --- send
def func1(): count = yield 222 print(count) yield 777 yield 888 g_obj = func1() # 生成器对象 generator object print(g_obj.__next__()) print(g_obj.send('wusir')) -----------------222 wusir 777
1,send具有next功能
2,send可以给上一个yield传值。
3,第一个取值不会使用send
4,最后一个yield不会得到send的值、
列表推导式:
能用列表推导式完成的,用python代码都可以完成。用一句话构建一个你想要的列表。
优点:简单,稍微难理解
缺点:不能用debug