迭代器和生成器

 
可迭代对象:可以直接作用于for循环的对象,称为可迭代对象。
     
可以直接用for循环的数据类型有:
  1. 集合数据类型,字符串,列表,元祖,字典,集合等。(都是Iterable对象,但不是Iterator,但是可以通过iter()变成Iterator对象)
  2. generator,包括生成器和带yield的generator function。 (调用返回一个Iterator)

可迭代对象都有一个__iter__方法 

例如:
>>> dir([]) ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__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']
判断一个对象是否是Iterable可迭代对象可以使用 isinstance() 方法
from collections import Iterable
>>> isinstance([],Iterable)
True
>>> isinstance({},Iterable)
True
>>> isinstance((x for x in range(5)),Iterable)
True
 
 
 
迭代器 Iterator:可以被__next__() 函数调用并不断返回下一个值的对象
 
可以使用isinstance()判断一个对象是否是Iterator
>>> from collections import Iterator
>>> it=(x for x in range(1,3))
>>> it
<generator object <genexpr> at 0x7fed717c9db0>   
>>> isinstance(it,Iterator)        
True

>>> isinstance([],Iterator)
False
迭代器特点:
  • 不能随机访问集合中的某个值,只能从头到尾依次访问
  • 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。只往前进不能后退
  • 仅仅在迭代到某个元素时才会计算它,不需要事先准备所有的元素。便于循环比较大的数据集合,节省内存。类似cat,more命令。

可迭代对象不一定是迭代器,迭代器一定是可迭代对象。

迭代器除了有__iter__方法,还有__next__方法

>>> it = iter(['a','b','c'])
>>> it
<list_iterator object at 0x7fd5bb4f76a0>
>>> dir(it)
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__length_hint__', '__lt__', '__ne__', '__new__', '__next__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__']

可以通过iter()将Iterable变成Iterator
# a.__next__()输出迭代器的下一个元素  等同于2.7里next(a)
>>> b= ('lily','jack','kang')
>>> a = iter(b) >>> a <tuple_iterator object at 0x7fed717cbf98> >>> next(a) #2.7写法 ,3里面用__next__() 'lily' >>> a.__next__() 'jack' >>> a.__next__() ## 已迭代完所有元素,再执行会报错StopIteration 'kang' >>> next(a) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration
# 迭代器也可以用for语句遍历
a = iter(('lily','jack','kang'))
for i in a:
    print(i,end=' ')
 

生成器:一个函数调用返回一个迭代器,这个函数就是生成器(generator)
  • 生成器是可以迭代的 但是只可以读取一次
生成器表达式:
>>> ge = (x for x in range(5))   #生成器使用 ()  区别于列表推导式[]
>>> ge
<generator object <genexpr> at 0x7fe0b4417048>
>>> ge.__next__()
0
>>> ge.__next__()   #可以通过__next__()方法不断返回下一个
1
>>> for i in ge:   #也可以用for循环
...     print(i)
... 
2
3
4

生成器函数

普通函数与生成器函数的区别:
普通函数调用直接返回一个结果,generator函数调用返回一个迭代器

# 遇到yield语句就返回,再次执行时从上次返回的yield语句处继续执行

def foo(num):
    while num > 0:
        num -= 1
        yield num     #return跳出循环后不能再返回,但是yield跳出此次循环还可以继续下一次
        print('减少1')
f = foo(3)    # 此时没有真正执行函数,只是把f变成一个迭代器
print(f.__next__())
print('-----')
print(f.__next__())
print(f.__next__())

------------->
2
-----
减少1
1
减少1
0
 
def odd():
    print('step1')
    yield 1            #运行完yield1停止
    print('step2')     #下一次执行从yield1后面开始执行
    yield 3
    print('step3')
    yield 5
o=odd()
print(next(o))   
------->
step1
1

print(next(o))
-------->
step2
2
........................................................................

def gen(func):
    for i in range(func):
        yield i

for x in gen(5):
    print(x,end=' ')
---->
0 1 2 3 4

#!/usr/bin/python3
def func():
    print('----start-------')
    a,b=0,1
    for i in range(4):
            print('1')
            yield b
            print('2')
            a,b=b,a+b
            print('3')
    print('------stop-----')

f=func()
print(next(f))
print(next(f))
print(next(f))
print(next(f))

--------------------输出-----start-------
    #print('1')
    #yeild b  返回1 第一次迭代完成
    #print('2') 下一次迭代从yeild b 后面开始
    #print('3')
    #print('1')
    #yeild b  第二次迭代完成
3
2     #yeild b 第三次迭代完成
3
3     #yeild b 第四次迭代完成
View Code





原文地址:https://www.cnblogs.com/xiaobaozi-95/p/9041872.html