看完这篇,你就知道Python生成器是什么
当前位置:以往代写 > Python教程 >看完这篇,你就知道Python生成器是什么
2019-06-14

看完这篇,你就知道Python生成器是什么

看完这篇,你就知道Python生成器是什么

生成器是 Python 低级开拓者最难领略的观念之一,虽被认为是 Python 编程中的高级技术,但在各类项目中可以到处见到生成器的身影,你得不得去领略它、利用它、甚至爱上它。

提到生成器,总不行制止地要把迭代器拉出来比拟着讲,生成器就是一个在行为上和迭代器很是雷同的工具,假如把迭代器比作 Android 系统,那么生成器就是 iOS,二者成果上差不多,可是生成器更优雅。

什么是迭代器

顾名思义,迭代器就是用于迭代操纵(for 轮回)的工具,它像列表一样可以迭代获取个中的每一个元素,任何实现了 __next__ 要领 (python2 是 next)的工具都可以称为迭代器。

它与列表的区别在于,构建迭代器的时候,不像列表把所有元素一次性加载到内存,而是以一种延迟计较(lazy evaluation)方法返回元素,这正是它的利益。好比列表含有中一千万个整数,需要占高出400M的内存,而迭代器只需要几十个字节的空间。因为它并没有把所有元素装载到内存中,而是比及挪用 next 要领时候才返回该元素(按需挪用 call by need 的方法,本质上 for 轮回就是不绝地挪用迭代器的next要领)。

以斐波那契数列为例来实现一个迭代器:

class Fib:
    def __init__(self, n):
        self.prev = 0
        self.cur = 1
        self.n = n
    def __iter__(self):
        return self
    def __next__(self):
        if self.n > 0:
            value = self.cur
            self.cur = self.cur + self.prev
            self.prev = value
            self.n -= 1
            return value
        else:
            raise StopIteration()
    # 兼容python2
    def __next__(self):
        return self.next()
f = Fib(10)
print([i for i in f])
#[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

什么是生成器

知道迭代器之后,就可以正式进入生成器的话题了。普通函数用 return 返回一个值,和 Java 等其他语言是一样的,然而在 Python 中尚有一种函数,用要害字 yield 来返回值,这种函数叫生成器函数,函数被挪用时会返回一个生成器工具,生成器本质上照旧一个迭代器,也是用在迭代操纵中,因此它有和迭代器一样的特性,独一的区别在于实现方法上纷歧样,后者越发简捷

最简朴的生成器函数:

>>> def func(n):
...     yield n*2
...
>>> func
<function func at 0x00000000029F6EB8>
>>> g = func(5)
>>> g
<generator object func at 0x0000000002908630>
>>>

func 就是一个生成器函数,挪用该函数时返回工具就是生成器 g ,这个生成器工具的行为和迭代器长短常相似的,可以用在 for 轮回等场景中。留意 yield 对应的值在函数被挪用时不会立即返回,而是挪用next要领时(本质上 for 轮回也是挪用 next 要领)才返回

>>> g = func(5)
>>> next(g)
10
>>> g = func(5)
>>> for i in g:
...     print(i)
...
10

那为什么要用生成器呢?显然,用生成器在逼格上要比迭代器高几个品级,它没有那么多冗长代码了,并且机能上一样的高效,为什么不消呢?来看看用生成器实现斐波那契数列有多简朴。

def fib(n):
    prev, curr = 0, 1
    while n > 0:
        n -= 1
        yield curr
        prev, curr = curr, curr + prev
print([i for i in fib(10)])
#[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

生成器表达式

#p#分页标题#e#

在前面一期「这样写代码更优雅」的文章内里曾经先容过列表推导式(list comprehension),生成器表达式与列表推导式长的很是像,可是它俩返回的工具纷歧样,前者返回生成器工具,后者返回列表工具。

>>> g = (x*2 for x in range(10))
>>> type(g)
<type 'generator'>
>>> l = [x*2 for x in range(10)]
>>> type(l)
<type 'list'>

前面已经先容过生成器的优势,就是迭代海量数据时,显然生成器更符合。

    关键字:

在线提交作业