Fork me on GitHub

迭代器和生成器

一、迭代器

1、定义

  迭代器(Iterator)是一种对象,它能够用来遍历标准模板库容器中的部分或全部元素,每个迭代器对象代表容器中的确定的地址。

满足什么样的条件才能成为迭代器呢?

  • 必须遵从迭代器协议 

迭代器协议:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代 。

满足什么样条件的对象才能提供一个next方法呢?

  • 对象内部定义了__iter__()以及__next__()方法
class Fibonacci(object):
    def __init__(self,m):
        self.m=m

    def __iter__(self):
        return self   #自身是一个迭代器

    def __next__(self):
        n, a, b = 0, 0, 1
        while n < self.m:
            print(b)
            a, b = b, a + b
            n += 1
f=Fibonacci(5) #f此时就是一个迭代器
for  i in f:
    print(i)

2、可迭代对象

  可迭代对象内部仅实现了__iter()__方法,可迭代对象可以通过._ iter _()方法转成迭代器。像listtupledictsetstr等都是直接可以使用for循环的对象都是可迭代对象。

list=[1,2,3]
#手动实现__iter__()方法
ilist=list.__iter__() 
print(ilist.__next__())#1
print(ilist.__next__())#2
print(ilist.__next__())#3

  而在for循环内部也是基于这样的实现方式,不过在for循环内部还进行了异常处理。

#####for循环的实质#######
list=[1,2,3]
#手动实现__iter__()方法
ilist=list.__iter__()
while True:
    try:
        print(ilist.__next__())
    except StopIteration as e:
        break

3、生成器

  可以理解为一种数据类型,这种数据类型自动实现了迭代器协议,即内部自动实现了__iter__()和__next__()方法,所以生成器不仅是可迭代对象而且还是迭代器对象。那么所有可迭代对象拥有的特性,它都拥有,比如for循环。

  如何构造一个生成器呢?

  在一个函数中通过yield关键字自动创建一个生成器函数,yield会自动构建好__next__()和__iter__()方法。

def test():
    yield 1
    yield 2
    yield 3

t=test()
print(type(t))#<class 'generator'>
print(t.__next__())#1
print(t.__next__())#2
print(t.__next__())#3

  进行for循环

for i in test():
    print(i)  #1,2,3

  所以生成器就是迭代器的一种,是构造迭代器的工具。

def Fibanocci(m):
    n,a,b = 0,0,1
    while n < m:
        yield b
        a,b=b,a+b
        n+=1
f = Fibanocci(5)   #f为一个迭代器对象,可以将其当作xrange来对待
while True:
    try:
        print(f.__next__())
    except StopIteration as e:        
      break

  在类中也是可以实现迭代器的:

class Fibonacci(object):
    def __init__(self,m):
        self.m=m

    def __iter__(self):
        n, a, b = 0, 0, 1
        while n < self.m:
            yield b
            a, b = b, a + b
            n += 1
f=Fibonacci(5) #f此时就是一个迭代器
for i in f:
    print(i)

  如何判断一个对象是可迭代对象呢?可以使用isinstance()进行判断。

from collections import Iterable
print(isinstance([], Iterable))#True
print(isinstance({}, Iterable))#True

  如何判断是否是生成器对象?可以使用isgenerator()进行判断

from inspect import isgenerator
def test():
    yield 1

t=test()
print(isgenerator(t))#True

  详情查看:https://docs.python.org/3/library/inspect.html#inspect.isgeneratorfunction

  如何判断是迭代器对象呢?可以使用isinstance()进行判断

from collections import Iterator
a="abc"
b=iter(a)
print(type(b))
print(isinstance(b,Iterator))#True

总结:

  迭代器对象内部实现了__iter__()和__next__()方法

  可迭代对象仅实现__iter__()方法,必须依靠对象调用__iter__()方法(iter(o))才能成为迭代器对象

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

  生成器既是可迭代对象,又是迭代器对象,相当于xrange。

  

 

posted @ 2019-06-18 14:34  iveBoy  阅读(286)  评论(0编辑  收藏  举报
TOP