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


    title: python迭代器与生成器
    data: 2018-4-7
    categories:

    • python
      tags:
    • python

    迭代器

    迭代器(Iterator)是访问集合元素的一种方式。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。

    迭代器有两个基本的方法:iter()next()

    python中对常见的迭代器使用场景是循环语句for,它用迭代器封装集合,并且逐个访问集合元素以执行循环体。比如:

    for num in range(5):
        print(num)
    

    其中的range()返回一个包含所指定元素的集合,而for语句将其封装成一个迭代器后访问。
    使用iter()调用可以将列表、集合转换成迭代器,比如下面的 t 就是一个迭代器:

    >>> mylist = [1,3,4,8,6,9]
    >>> t = iter(mylist)
    >>> print(t)
    <listiterator object at 0x00000000025F39B0>
    

    迭代器和普通python对象的区别是迭代器有一个next()方法,每次调用该方法可以放回一个元素。调用者(比如for语句)可以通过不断调用next()方法来逐个访问集合元素。比如:

    >>> iter = iter(range(5))
    >>> print iter.next()
    0
    >>> print iter.next()
    1
    >>> print iter.next()
    2
    ...
    

    调用者可以一直这样调用next()方法来访问迭代器,直到next()返回StopIteration异常表示迭代已经完成。

    创建一个迭代器

    把一个类作为一个迭代器使用需要在类中实现两个方法 __iter__() __next__()
    Python 的构造函数为 __init__(), 它会在对象初始化的时候执行。

    __iter__() 方法返回一个特殊的迭代器对象, 这个迭代器对象实现了 __next__() 方法并通过 StopIteration 异常标识迭代的完成。

    __next__() 方法(Python 2 里是 next())会返回下一个迭代器对象。

    创建一个返回数字的迭代器,初始值为 1,逐步递增 1:

    #python3
    class MyNumbers:
      def __iter__(self):
        self.a = 1
        return self
     
      def __next__(self):
        x = self.a
        self.a += 1
        return x
     
    myclass = MyNumbers()
    myiter = iter(myclass)
     
    print(next(myiter))
    print(next(myiter))
    print(next(myiter))
    print(next(myiter))
    print(next(myiter))
    

    执行输出结果为:

    1
    2
    3
    4
    5
    

    StopIteration

    StopIteration 异常用于标识迭代的完成,防止出现无限循环的情况,在 __next__() 方法中我们可以设置在完成指定循环次数后触发 StopIteration 异常来结束迭代。
    在 10 次迭代后停止执行:

    #python3
    class MyNumbers:
      def __iter__(self):
        self.a = 1
        return self
     
      def __next__(self):
        if self.a <= 10:
          x = self.a
          self.a += 1
          return x
        else:
          raise StopIteration
     
    myclass = MyNumbers()
    myiter = iter(myclass)
     
    for x in myiter:
      print(x)
    

    执行输出结果为:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    

    生成器

    在 Python 中,使用了 yield 的函数被称为生成器(generator)。

    跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。

    在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。

    调用一个生成器函数,返回的是一个迭代器对象。

    以下实例使用 yield 实现斐波那契数列:

    #!/usr/bin/python3
    import sys
     
    def fibonacci(n): # 生成器函数 - 斐波那契
        a, b, counter = 0, 1, 0
        while True:
            if (counter > n): 
                return
            yield a
            a, b = b, a + b
            counter += 1
    f = fibonacci(10) # f 是一个迭代器,由生成器返回生成
     
    while True:
        try:
            print (next(f), end=" ")
        except StopIteration:
            sys.exit()
    

    执行以上程序,输出结果如下:

    0 1 1 2 3 5 8 13 21 34 55
    

    使用 yield

    #!/usr/bin/python3
    import sys
    
    def fibonacci(n,w=0): # 生成器函数 - 斐波那契
        a, b, counter = 0, 1, 0
        while True:
            if (counter > n): 
                return
            yield a
            a, b = b, a + b
            print('%d,%d' % (a,b))
            counter += 1
    f = fibonacci(10,0) # f 是一个迭代器,由生成器返回生成
    
    while True:
        try:
            print (next(f), end=" ")
        except :
            sys.exit()
    

    输出结果:

    0 1,1
    1 1,2
    1 2,3
    2 3,5
    3 5,8
    5 8,13
    8 13,21
    13 21,34
    21 34,55
    34 55,89
    55 89,144
    

    不使用 yield

    #!/usr/bin/python3
    
    import sys
    
    def fibonacci(n,w=0): # 生成器函数 - 斐波那契
        a, b, counter = 0, 1, 0
        while True:
            if (counter > n): 
                return
            #yield a
            a, b = b, a + b
            print('%d,%d' % (a,b))
            counter += 1
    f = fibonacci(10,0) # f 是一个迭代器,由生成器返回生成
    
    while True:
        try:
            print (next(f), end=" ")
        except :
            sys.exit()
    

    输出结果:

    1,1
    1,2
    2,3
    3,5
    5,8
    8,13
    13,21
    21,34
    34,55
    55,89
    89,144
    

    区别

    第二种没有yield时,函数只是简单执行,没有返回迭代器f。这里的迭代器可以用生成l列表来理解一下:

    >>> l = [i for i in range(0,15)]
    >>> print(l)
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
    >>> m = (i for i in range(0,15))
    >>> print(m)
    <generator object <genexpr> at 0x104b6f258>
    >>> for g in m:
    ...     print(g,end=', ')
    ... 
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
    

    这里的m就像上面的f一样,是迭代器。

    参考:http://www.runoob.com/python3/python3-iterator-generator.html 下面的笔记

  • 相关阅读:
    【Oracle】权限
    【Oracle】利用trace文件重建控制文件
    【Oracle】创建概要文件
    【Oracle】创建角色
    【Oracle】创建用户
    【Oracle】glogin.sql脚本模板
    夺命雷公狗---DEDECMS----1dedecms的安装过程
    夺命雷公狗---微信开发63----微信开发总结篇
    夺命雷公狗---微信开发62----所以memcache对access_token进行全局缓存优化
    夺命雷公狗---微信开发61----在线点播电影网2之电影网之个人中心
  • 原文地址:https://www.cnblogs.com/id88/p/14210843.html
Copyright © 2011-2022 走看看