搜索
首页后端开发Python教程一文详解python生成器

本篇文章给大家带来了关于python的相关知识,其中主要介绍了关于生成器的相关问题,包括了生成器的概念、生成器的执行过程、yield以及生成器方法等内容,下面一起来看一下,希望对大家有帮助。

一文详解python生成器

推荐学习:python视频教程

本篇文章给大家带来了关于Python的相关知识,其中主要介绍了关于生成器的相关问题,包括了生成器的概念、生成器的执行过程、yield以及生成器方法等内容,下面一起来看一下,希望对大家有帮助。

1. 生成器概念

生成器(英文:generator)是一个非常迷人的东西,也常被认为是 Python 的高级编程技能。不过,我依然很

乐意在这里跟读者——尽管你可能是一个初学者——探讨这个话题,因为我相信各位大佬看本教程的目的,绝非仅仅 将自己限制于初学者水平,一定有一颗不羁的心——要成为 Python 高手。那么,开始了解生成器吧。

还记得上节的“迭代器”吗?生成器和迭代器有着一定的渊源关系。生成器必须是可迭代的,诚然它又不仅仅是

迭代器,但除此之外,又没有太多的别的用途,所以,我们可以把它理解为非常方便的自定义迭代器。

2. 简单的生成器

>>> my_generator = (x*x for x in range(4))

这是不是跟列表解析很类似呢?仔细观察,它不是列表,如果这样的得到的才是列表:

>>> my_list = [x*x for x in range(4)]

以上两的区别在于是 [] 还是 () ,虽然是细小的差别,但是结果完全不一样。

>>> dir(my_generator)
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__',
'__iter__',
'__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'gi_code', 'gi_frame', 'gi_running',
'next',
'send', 'throw']

为了容易观察,我将上述结果进行了重新排版。是不是发现了在迭代器中必有的方法 __inter__() 和 next() ,这说明它是迭代器。如果是迭代器,就可以用 for 循环来依次读出其值

>>> for i in my_generator:
... print i
...
0
1
4
9
>>> for i in my_generator:
... print i
...

当第一遍循环的时候,将 my_generator 里面的值依次读出并打印,但是,当再读一次的时候,就发现没有任何结果。这种特性也正是迭代器所具有的。

如果对那个列表,就不一样了:

>>> for i in my_list:
... print i
...
0
1
4
9
>>> for i in my_list:
... print i
...
0
1
4
9

难道生成器就是把列表解析中的 [] 换成 () 就行了吗?这仅仅是生成器的一种表现形式和使用方法罢了,仿照

列表解析式的命名,可以称之为“生成器解析式”(或者:生成器推导式、生成器表达式)。

生成器解析式是有很多用途的,在不少地方替代列表,是一个不错的选择。特别是针对大量值的时候,如上节所说的,列表占内存较多,迭代器(生成器是迭代器)的优势就在于少占内存,因此无需将生成器(或者说是迭代器)实例化为一个列表,直接对其进行操作,方显示出其迭代的优势。比如:

>>> sum(i*i for i in range(10))
285

注意观察上面的 sum() 运算,不要以为里面少了一个括号,就是这么写。是不是很迷人?如果列表,你

不得不:

>>> sum([i*i for i in range(10)])
285

               通过生成器解析式得到的生成器,掩盖了生成器的一些细节,并且适用领域也有限。下面就要剖析生成器的内部,深入理解这个魔法工具。

3. 定义和执行过程

yield 这个词在汉语中有“生产、出产”之意,在 Python 中,它作为一个关键词(你在变量、函数、类的名称中

就不能用这个了),是生成器的标志。

>>> def g():
... yield 0
... yield 1
... yield 2
...
>>> g
<function g at 0xb71f3b8c>

建立了一个非常简单的函数,跟以往看到的函数唯一不同的地方是用了三个 yield 语句。然后进行下面的操作:

>>> ge = g()
>>> ge
<generator object g at 0xb7200edc>
>>> type(ge)
<type &#39;generator&#39;>

上面建立的函数返回值是一个生成器(generator)类型的对象。

>>> dir(ge)
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__iter__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'gi_code', 'gi_frame', 'gi_running', 'next', 'send', 'throw']

在这里看到了 __iter__() 和 next() ,说明它是迭代器。既然如此,当然可以:

>>> ge.next()
0
>>> ge.next()
1
>>> ge.next()
2
>>> ge.next()
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
StopIteration

从这个简单例子中可以看出,那个含有 yield 关键词的函数返回值是一个生成器类型的对象,这个生成器对象就是迭代器。

我们把含有 yield 语句的函数称作生成器。生成器是一种用普通函数语法定义的迭代器。通过上面的例子可以看出,这个生成器(也是迭代器),在定义过程中并没有像上节迭代器那样写 __inter__() 和 next() ,而是只要用了 yield 语句,那个普通函数就神奇般地成为了生成器,也就具备了迭代器的功能特性。

yield 语句的作用,就是在调用的时候返回相应的值。详细剖析一下上面的运行过程:

1. ge = g() :除了返回生成器之外,什么也没有操作,任何值也没有被返回。

2. ge.next() :直到这时候,生成器才开始执行,遇到了第一个 yield 语句,将值返回,并暂停执行(有的称之

为挂起)。

3. ge.next() :从上次暂停的位置开始,继续向下执行,遇到 yield 语句,将值返回,又暂停。

4. gen.next() :重复上面的操作。

5. gene.next() :从上面的挂起位置开始,但是后面没有可执行的了,于是 next() 发出异常。

从上面的执行过程中,发现 yield 除了作为生成器的标志之外,还有一个功能就是返回值。那么它跟 return 这个返回值有什么区别呢?

4. yield

为了弄清楚 yield 和 return 的区别,我写了两个函数来掩饰:

>>> def r_return(n):
... print "You taked me."
... while n > 0:
... print "before return"
... return n
... n -= 1
... print "after return"
...
>>> rr = r_return(3)
You taked me.
before return
>>> rr
3

从函数被调用的过程可以清晰看出, rr = r_return(3) ,函数体内的语句就开始执行了,遇到 return,将值返

回,然后就结束函数体内的执行。所以 return 后面的语句根本没有执行。这是 return 的特点

下面将 return 改为 yield:

>>> def y_yield(n):
... print "You taked me."
... while n > 0:
...     print "before yield"
...     yield n
...     n -= 1
...     print "after yield"
...
>>> yy = y_yield(3) #没有执行函数体内语句
>>> yy.next() #开始执行
You taked me.
before yield
3 #遇到 yield,返回值,并暂停
>>> yy.next() #从上次暂停位置开始继续执行
after yield
before yield
2 #又遇到 yield,返回值,并暂停
>>> yy.next() #重复上述过程
after yield
before yield
1
>>> yy.next()
after yield #没有满足条件的值,抛出异常
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
StopIteration

结合注释和前面对执行过程的分析,读者一定能理解 yield 的特点了,也深知与 return 的区别了。

一般的函数,都是止于 return。作为生成器的函数,由于有了 yield,则会遇到它挂起,如果还有 return,遇到它就直接抛出 SoptIteration 异常而中止迭代。

#!/usr/bin/env Python
# coding=utf-8

def fibs(max):
    """
    斐波那契数列的生成器
    """
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n = n + 1
if __name__ == "__main__":
    f = fibs(10)
    for i in f:
        print i ,

运行结果如下:

$ python 21501.py
1 1 2 3 5 8 13 21 34 55

用生成器方式实现的斐波那契数列是不是跟以前的有所不同了呢?大家可以将本教程中已经演示过的斐波那契数列实现方式做一下对比,体会各种方法的差异。

经过上面的各种例子,已经明确,一个函数中,只要包含了 yield 语句,它就是生成器,也是迭代器。这种方式显然比前面写迭代器的类要简便多了。但,并不意味着上节的就被抛弃。是生成器还是迭代器,都是根据具体的使用情景而定。

5. 生成器方法

在 python2.5 以后,生成器有了一个新特征,就是在开始运行后能够为生成器提供新的值。这就好似生成器

和“外界”之间进行数据交流。

>>> def repeater(n):
... while True:
...     n = (yield n)
...
>>> r = repeater(4)
>>> r.next()
4
>>> r.send("hello")
'hello

当执行到 r.next() 的时候,生成器开始执行,在内部遇到了 yield n 挂起。注意在生成器函数中, n = (yield

n) 中的 yield n 是一个表达式,并将结果赋值给 n,虽然不严格要求它必须用圆括号包裹,但是一般情况都这

么做,请大家也追随这个习惯。

当执行 r.send("hello") 的时候,原来已经被挂起的生成器(函数)又被唤醒,开始执行 n = (yield n) ,也就是

讲 send() 方法发送的值返回。这就是在运行后能够为生成器提供值的含义。

如果接下来再执行 r.next() 会怎样?

>>> r.next()

什么也没有,其实就是返回了 None。按照前面的叙述,读者可以看到,这次执行 r.next() ,由于没有传入任何值,yield 返回的就只能是 None.

还要注意,send() 方法必须在生成器运行后并挂起才能使用,也就是 yield 至少被执行一次。如果不是这样:

>>> s = repeater(5)
>>> s.send("how")
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
TypeError: can't send non-None value to a just-started generator

就报错了。但是,可将参数设为 None:

>>> s.send(None)
5

这是返回的是调用函数的时传入的值。

此外,还有两个方法:close() 和 throw()

• throw(type, value=None, traceback=None):用于在生成器内部(生成器的当前挂起处,或未启动时在定

义处)抛出一个异常(在 yield 表达式中)。

• close():调用时不用参数,用于关闭生成器。

推荐学习:python视频教程

以上是一文详解python生成器的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文转载于:CSDN。如有侵权,请联系admin@php.cn删除
详细讲解Python之Seaborn(数据可视化)详细讲解Python之Seaborn(数据可视化)Apr 21, 2022 pm 06:08 PM

本篇文章给大家带来了关于Python的相关知识,其中主要介绍了关于Seaborn的相关问题,包括了数据可视化处理的散点图、折线图、条形图等等内容,下面一起来看一下,希望对大家有帮助。

详细了解Python进程池与进程锁详细了解Python进程池与进程锁May 10, 2022 pm 06:11 PM

本篇文章给大家带来了关于Python的相关知识,其中主要介绍了关于进程池与进程锁的相关问题,包括进程池的创建模块,进程池函数等等内容,下面一起来看一下,希望对大家有帮助。

Python自动化实践之筛选简历Python自动化实践之筛选简历Jun 07, 2022 pm 06:59 PM

本篇文章给大家带来了关于Python的相关知识,其中主要介绍了关于简历筛选的相关问题,包括了定义 ReadDoc 类用以读取 word 文件以及定义 search_word 函数用以筛选的相关内容,下面一起来看一下,希望对大家有帮助。

归纳总结Python标准库归纳总结Python标准库May 03, 2022 am 09:00 AM

本篇文章给大家带来了关于Python的相关知识,其中主要介绍了关于标准库总结的相关问题,下面一起来看一下,希望对大家有帮助。

Python数据类型详解之字符串、数字Python数据类型详解之字符串、数字Apr 27, 2022 pm 07:27 PM

本篇文章给大家带来了关于Python的相关知识,其中主要介绍了关于数据类型之字符串、数字的相关问题,下面一起来看一下,希望对大家有帮助。

分享10款高效的VSCode插件,总有一款能够惊艳到你!!分享10款高效的VSCode插件,总有一款能够惊艳到你!!Mar 09, 2021 am 10:15 AM

VS Code的确是一款非常热门、有强大用户基础的一款开发工具。本文给大家介绍一下10款高效、好用的插件,能够让原本单薄的VS Code如虎添翼,开发效率顿时提升到一个新的阶段。

详细介绍python的numpy模块详细介绍python的numpy模块May 19, 2022 am 11:43 AM

本篇文章给大家带来了关于Python的相关知识,其中主要介绍了关于numpy模块的相关问题,Numpy是Numerical Python extensions的缩写,字面意思是Python数值计算扩展,下面一起来看一下,希望对大家有帮助。

python中文是什么意思python中文是什么意思Jun 24, 2019 pm 02:22 PM

pythn的中文意思是巨蟒、蟒蛇。1989年圣诞节期间,Guido van Rossum在家闲的没事干,为了跟朋友庆祝圣诞节,决定发明一种全新的脚本语言。他很喜欢一个肥皂剧叫Monty Python,所以便把这门语言叫做python。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前By尊渡假赌尊渡假赌尊渡假赌

热工具

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

将Eclipse与SAP NetWeaver应用服务器集成。

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

安全考试浏览器

安全考试浏览器

Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。