可迭代对象
可以被for循环迭代的对象为可迭代对象(Iterable)
可以使用isinstance()判断一个对象是否是Iterable对象:
>>> from collections import Iterable
>>> isinstance([], Iterable)
True
>>> isinstance({}, Iterable)
True
>>> isinstance('abc', Iterable)
True
>>> isinstance((x for x in range(10)), Iterable)
True
>>> isinstance(100, Iterable)
False
迭代器
迭代器是一个可以记住遍历的位置的对象。
迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
迭代器有两个基本的方法:iter() 和 next()。
i = iter('asd')
next(i)
>>>'a'
next(i)
>>>'s'
next(i)
>>>'d'
next(i)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
当序列遍历完时,将抛出一个StopIteration(停止迭代)异常。
迭代器优点
1、“流式”数据处理方式*少内存消耗,节省内存空间
2、很方便使用,且只能取所有的数据取一次
迭代器的内部
可迭代对象:
对象里面包含iter()方法的实现,对象的iter函数经调用之后会返回一个迭代器,里面包含具体数据获取的实现
迭代器:
包含有next方法的实现,在正确范围内返回期待的数据以及超出范围后能够抛出StopIteration的错误停止迭代。
迭代器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。
可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。
生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator
把list、dict、str等Iterable变成Iterator可以使用iter()函数:
一个实现了iter方法的对象是可迭代的,一个实现next方法的对象则是迭代器
生成器
生成器的本质就是迭代器
迭代器 我们知道是用来迭代可迭代对象的,而生成器是用来迭代方法的
我们知道的迭代器有两种:一种是调用方法直接返回的,一种是可迭代对象通过执行iter方法得到的,迭代器有的好处是可以节省内存。
如果在某些情况下,我们也需要节省内存,就只能自己写。我们自己写的这个能实现迭代器功能的东西就叫生成器。
生成器Generator:
本质:迭代器(所以自带了iter方法和next方法,不需要我们去实现)
特点:惰性运算,开发者自定义
1.生成器函数:
常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重它离开的地方继续执行。
只要有yield的关键字的函数就是生成器函数
一个包含yield关键字的函数就是一个生成器函数。yield可以为我们从函数中返回值,但是yield又不同于return,return的执行意味着程序的结束,调用生成器函数不会得到返回的具体的值,而是得到一个可迭代的对象。每一次获取这个可迭代对象的值,就能推动函数的执行,获取新的返回值。直到函数执行结束。
特点
调用函数的之后函数不执行,返回一个生成器
每次调用next方法的时候会取到一个值
直到取完最后一个,在执行next会报错
生成器是特殊的迭代器
迭代器需要手动记录迭代位置
生成器使用yield自动记录迭代的位置
def fei(num):
a = 0
b = 1
current_index = 0
print('11111111111')
while current_index < num:
a, b = b, a + b
current_index += 1
yield a, b
# yield b
print('222222222222')
result = fei(5)
print(next(result))
print('第一次next完成')
print(next(result))
print('第二次next完成')
输出结果
11111111111
(1, 1)
第一次next完成
222222222222
(1, 2)
第二次next完成
yield from
def gen1():
for c in 'AB':
yield c
for i in range(3):
yield i
print(list(gen1()))
def gen2():
yield from 'AB'
yield from range(3)
print(list(gen2()))
输出结果:
['A', 'B', 0, 1, 2]
['A', 'B', 0, 1, 2]
yield的用法
yield 是一个类似 return的关键字,迭代一次遇到yield时就返回yield后面的值。重点是:下一次迭代时,从上一次迭代遇到的yield后面的代码开始执行。
简要理解:yield就是 return 返回一个值,并且记住这个返回的位置,下次迭代就从这个位置后开始。
# 斐波那契
def func(n):
a,b = 0,1
while n > 0:
yield b
a,b = b,a+b
n -= 1
def sum(n):
return list(func(n))
print(sum(5))
输出的结果:
[1, 1, 2, 3, 5]
def yield_test(n):
for i in range(n):
yield call(i)
print("i=",i)
#做一些其它的事情
print("do something.")
print("end.")
def call(i):
return i*2
#使用for循环
for i in yield_test(5):
print(i,",")
输出的结果:
0 ,
i= 0
2 ,
i= 1
4 ,
i= 2
6 ,
i= 3
8 ,
i= 4
do something.
end.