可迭代对象和迭代器
可迭代对象:内置方法有__iter__方法的
像基本数据类型:list, dict, tuple, str都是可迭代对象。但同时,他们没有__next__,所以不能叫做迭代器。
迭代器:内置方法有__iter__和__next__的
因为迭代器都有__iter__,所以,迭代器都是可迭代对象。
可迭代对象执行__iter__之后,返回的是一个迭代器。
* 文件对象(文件句柄)里面既有__iter__, __next__, 文件对象执行__iter__之后,还是文件对象本身。文件对象本身就是一个迭代器。
* 迭代器对象无论执行多少次__iter__, 得到的都会是一个迭代器对象。
for循环的本质:
1、将in 后面的可迭代对象,调用__iter__,返回一个迭代器对象。
2、循环调用迭代器的__next__方法
3、捕捉异常 StopIteration, 跳出__next__循环。
迭代器的优缺点:
优点:不占内存空间、不依赖索引
缺点:不能精确找值、会报错。
生成器
我们自己造的迭代器叫生成器。生成器里面的代码块不会执行,除非调用__next__方法。
关键字yield:
yield提供了一种自定义生成器方式
yield会暂停函数的运行
yield返回任意数据类型
yield后面跟的值就是我们调用__next__方法后得到的值
yield与return的异同点:
相同点:都可以返回值,都可以返回多个值
不同点:
yield能重复返回多次,函数不会结束运行。
return只能返回一次,返回一次后,函数运行结束
生成器表达式: g = (i for i in range(1, 10000000) if i != 4)
生成器表达式,用两个小括号括起来。
1、利用生成器重写range
def my_range(start, stop, step=1): while True: if start < stop: yield start start += step else: break
2、面试题
def add(n,i): return n+i def test(): for i in range(4): yield i g=test() for n in [1,10]: g=(add(n,i) for i in g) print(n) res=list(g) A. res=[10,11,12,13] B. res=[11,12,13,14] C. res=[20,21,22,23] D. res=[21,22,23,24] 重点:生成器不会执行函数体内代码,除非调用__next__