• 生成器


    生成器

    在这一节我们学习有关 Python 生成器(Generators)的知识。生成器是更简单的创建迭代器的方法,这通过在函数中使用 yield 关键字完成:

    >>> def my_generator():
    ...     print("Inside my generator")
    ...     yield 'a'
    ...     yield 'b'
    ...     yield 'c'
    ...
    >>> my_generator()
    <generator object my_generator at 0x7fbcfa0a6aa0>
    

    在上面的例子中我们使用 yield 语句创建了一个简单的生成器。我们能在 for 循环中使用它,就像我们使用任何其它迭代器一样。

    >>> for char in my_generator():
    ...     print(char)
    ...
    Inside my generator
    a
    b
    c
    

    在下一个例子里,我们会使用一个生成器函数完成与 Counter 类相同的功能,并且把它用在 for 循环中。

    >>> def counter_generator(low, high):
    ...     while low <= high:
    ...        yield low
    ...        low += 1
    ... 
    >>> for i in counter_generator(5,10):
    ...     print(i, end=' ')
    ... 
    5 6 7 8 9 10
    

    在 While 循环中,每当执行到 yield 语句时,返回变量 low 的值并且生成器状态转为挂起。在下一次调用生成器时,生成器从之前冻结的地方恢复执行然后变量 low 的值增一。生成器继续 while 循环并且再次来到 yield 语句...

    当你调用生成器函数时它返回一个生成器对象。如果你把这个对象传入 dir() 函数,你会在返回的结果中找到 __iter____next__ 两个方法名。

    此处输入图片的描述

    我们通常使用生成器进行惰性求值。这样使用生成器是处理大数据的好方法。如果你不想在内存中加载所有数据,你可以使用生成器,一次只传递给你一部分数据。

    os.path.walk() 函数是最典型的这样的例子,它使用一个回调函数和当前的 os.walk 生成器。使用生成器实现节约内存。

    我们可以使用生成器产生无限多的值。以下是一个这样的例子。

    >>> def infinite_generator(start=0):
    ...     while True:
    ...         yield start
    ...         start += 1
    ...
    >>> for num in infinite_generator(4):
    ...     print(num, end=' ')
    ...     if num > 20:
    ...         break
    ...
    4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
    

    如果我们回到 my_generator() 这个例子,我们会发现生成器的一个特点:它们是不可重复使用的。

    >>> g = my_generator()
    >>> for c in g:
    ...     print(c)
    ...
    Inside my generator
    a
    b
    c
    >>> for c in g:
    ...     print(c)
    ...
    

    我们无法创建一个可重复使用的生成器,但可以创建一个对象,将它的 __iter__方法调用得到一个生成器,举例如下:

    >>> class Counter(object):
    ...     def __init__(self, low, high):
    ...         self.low = low
    ...         self.high = high
    ...     def __iter__(self):
    ...          counter = self.low
    ...          while self.high >= counter:
    ...              yield counter
    ...              counter += 1
    ...
    >>> gobj = Counter(5, 10)
    >>> for num in gobj:
    ...     print(num, end=' ')
    ...
    5 6 7 8 9 10
    >>> for num in gobj:
    ...     print(num, end=' ')
    ...
    5 6 7 8 9 10
    

    上面的 gobj 并不是生成器或迭代器,因为它不具有 __next__ 方法,只是一个可迭代对象,生成器是一定不能重复循环的。而 gobj.__iter__() 是一个生成器,因为它是一个带有 yield 关键字的函数。

    如果想要使类的实例变成迭代器,可以用 __iter__ + __next__ 方法实现:

    >>> from collections import Iterator
    >>> class Test():
    ...:     def __init__(self, a, b):
    ...:         self.a = a
    ...:         self.b = b
    ...:     def __iter__(self):
    ...:         return self
    ...:     def __next__(self):
    ...:         self.a += 1
    ...:         if self.a > self.b:
    ...:             raise StopIteration()
    ...:         return self.a
    ...:     
    
    >>> test = Test(5, 10)
    
    >>> isinstance(test, Iterator)
    True
    
  • 相关阅读:
    互联网与局域网(四)
    Socket介绍(五)
    HttpClient(七)
    TCP协议与HTTP协议区别
    TCP连接的三次握手
    context-param和init-param区别
    【HPU】[1736]老王修马路(二)
    【HPU】[1735]老王修马路(一)
    【HPU】[1734]老王修公园
    【HPU】[1733]神奇的数字9
  • 原文地址:https://www.cnblogs.com/huanyinglvtuan/p/13021939.html
Copyright © 2020-2023  润新知