zoukankan      html  css  js  c++  java
  • 迭代器和生成器

    一、迭代器

    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。

      

  • 相关阅读:
    Vue 单向数据流&双向数据绑定原理
    Arguments对象
    类数组对象(array-like objects)
    ...theArgs剩余参数
    vue 深度选择器/deep/报错(标红)
    修改mandMobile下拉菜单样式
    PC端input maxlength 失效问题
    el-input 正则限制输入为非负整数
    Mac鼠标左右键都是右键
    Vue双向数据绑定简易实现
  • 原文地址:https://www.cnblogs.com/shenjianping/p/11042098.html
Copyright © 2011-2022 走看看