西南大学研究生院,Python协程一从generator和yield表达式说起,桐城

Python协程系列(一)——从generator和yield表达式说起

python进阶教程

机器学习

进入正文

Python协程系列(一)——生成器generator以及yield表达式详解

声明:本文将具体解说python协程的完成机理,为了完全的弄理解它到底是怎样一回事,鉴于篇幅较长,将完全从最简略的yield说起从最简略的生成器开端说起,由于许多看到这样一句话的时分很懵,即“yield也是一种简略的协程”,这到底是为什么呢?本次系列文章“python协程系列文章”将从西南大学研究生院,Python协程一从generator和yield表达式说起,桐城最简略的生成器、yield、yield from说起,然后具体解说asyncio的完成办法。本文首要解说Python的生成器的各种具体操作,以及yield表达式的具体运用。

目录

生成器generator以及yield表达式详解

1、最简略的生成器

2、send()办法的运用

3、yield句子的用法总结

4、迭代器(生成器)的send办法详解

——首要意图是“交互”

5、生成器throw的办法用法

6、生成器的发动与封闭close

6.1 生成器的发动

6.2 生成器的封闭——经过close()办法

7、生成器的停止迭代——StopIteration

留意:关于什么是可迭代目标、什么是生成器、什么是迭代器这儿不再赘述。

yield是完成生成器的重要关键字,可是yield句子有一些非常重要的小细节需求留意,或许咱们在写一个简略的生成器的时分有许多东西没有用到,这儿将分状况逐个评论。特别是生成器的三个重要办法,一个是next()、一个是send(),一个是throw(),他们到底有什么样的效果。

01

最简略的生成器

def my_generator(n):

for i in range(n):

yield i

02

send()办法的运用

def my_generator(n):

for i in range(n):

temp=yield i

print(f'我是{temp}')

g=my_generator(5)

print(next(g)) #输出0

print(next(g)) #输出1

g.send(100) #原本输出2,可是传入新的值100,改为输出100

print(next(g)) #输出3

print(next(g)) #输出4

'''

0 #榜首次迭代

---------------------

我是None

1 #第2次迭代

--------------西南大学研究生院,Python协程一从generator和yield表达式说起,桐城-------

我是100 #第三次迭代

---------------------

我是None #第四次迭代

3

---------------------

我是None #第五次迭代

4

'''

从上面能够看出yield句子与一般函数的return句子的差异在哪里了,首要会集在以下几点

(1)return 不能写成“temp=return xxxx”的方式,会提示语法过错,可是yield能够写成“temp=yield xxxx”的方式;

(2)一般函数return后边的句子都是不会再履行的,可是yield句子后边的仍然会履行,可是需求留意的是,由于“推迟加西南大学研究生院,Python协程一从generator和yield表达式说起,桐城载”特性,yield后边的代码并不是在榜首次迭代的时分履行的,而是第2次迭代的时分才履行榜首次yield后边没有履行的代码。也正是这个特性,构成了yield为什么是完成协程的最简略完成。

(3)运用send()办法传进去的值,实际上便是yield表达式回来的值,这便是为什么前面每次输出print(temp)都打印出None,由于没有send值,所以temp为None,可是send(100)之后却打印100,由于此刻temp便是100了。

我乃至还能够在yield后边不放任何东西,如下代码:

def my_generator(n):

for i in range(n):

temp = yield #yield后边没有任何东西,这时分无法迭代值,每次都是None

print(f'我是{temp}')

g=my_generator(5)

print(next(g))

print(next(g))

g.send(100)

print(next(g))

print(next(g))

'''

None

-----------------------

我是None

None

-----------------------

我是100 #这个100并不是迭代的100哦,而是send进去100,实际上是temp的打印值

-----------------------

我是None

None

-----------------------

我是None

None

'''

03

yield句子的用法总结

yield的一般方式为:

temp=yield 表达式(每次迭代要回来的值)

(1)假如要回来确认的值,后边的表达式不行省掉,绝大部分状况下咱们也西南大学研究生院,Python协程一从generator和yield表达式说起,桐城不省掉,不然只能回来None;

(2)假如运用了send(value),传递进去的那个value回替代那个表达式的值,而且会将传递进去的那个值回来给yield表达式的成果temp,所以假如想在yield后边运用传递进去的那个值,有必要要有运用temp,不然无法运用;

(3)yield句子的一般方式

temp=yield expression (引荐:既能够回来迭代的值,也能够承受send进去的参数并运用)

yield expression(也能够运用:)

temp=yield (不引荐)

yield (不引荐)

04

迭代器(生成器)的send办法详解

检查send的界说,得到send(arg)是有回来值的,而且他的回来值便是原本我应该迭代出来的那个值,如下所示:

def my_generator(n):

for i in range(n):

yield i

g=my_generator(5)

print(next(g))

print(next(g))

g.send(100)

print(next(g))

print(next(g))

'''

0

1

3

4

'''

#咱们发现尽管100传进去了,可是他并没有迭代出来,那原本的2去哪里了呢?send(100)实际上便是回来的2

假如改为以下代码:

print(next(g))

print(next(g))

a=g.send(100)

print('我是{0}'.format(a))

print(next(g))

print(next(g))

'''

0

1

我是2

3

4

'''

send(arg)办法总结:

(1)它的首要效果是,当我需求手动更改生成器里边的某一个值而且运用它,则send发送进去一个数据,然后保存到yield句子的回来值,以供给使苏门答腊鼠猴用

(2)send(arg)的回来值便是那个原本应该被迭代出来的那个值。这样既能够确保我能够传入新的值,原本的值也不会弄丢

05

生成器throw的办法用法

这个函数相比较于前面的next()、send()来说愈加杂乱,先看一下它的函数描绘:

raise exception in generator,return next yielded 桃乐猪value or StopIteration,即在生成器中抛出反常,而且这个throw函数会回来下一个要迭代的值或者是StopIteration。仍是经过几个比如西南大学研究生院,Python协程一从generator和yield表达式说起,桐城来看吧!

def my_generator():

yield 'a'

yield 'b'

yield 'c'

g=闺华记my_generator()

print(next(g))

print(next(g))

print('-------------------------')

print(g.throw(StopIteration))

print(next(g))

'''运转成果为:

a

b

-------------------------

StopIteration

'''

由于在迭代完 b 之后,就触发了StopIteration反常,这相当于后边的 ‘c’ 现已没用了,越过了c ,c再也不会履行,就中断了,所以后边的 'c'再也不会迭代,所以这儿不会再回来任何值,回来的是StopIteration。

再看一个比如:

def my_gene谈笑靖rator():

try:

yield 'a'

yield 'b'

yield 'c'

yield 'd'

yield 'e'

except ValueError:

print('触发“ValueError"了')

except TypeError:

print('触发“TypeError"了')

g=my_generator()

print(next(g))

print(next(g))

print('-------------------------')

print(g.throw无痛起床法(ValueError))

print('-------------------------')

print(next(g))

print(next(g))

print('-------------------------')

print(g.throw(TypeError))

print('-------------------------')

print(next(g))

'''运转成果为:

a

b

-------------------------

触发“ValueError"了

StopIteration

'''

当前面两次履行了a和b之后,向生成器扔进去一个反常,触发ValueError反常,这时分意味着try后边的c、d、e现已作废了,不会再有用,这个生成器现已停止了,因而g.throw()会回来StopIteration。

再看一个比如:

def my_generator():

while True:

try:

yield 'a'

yield 'b'

yield 'c'

yield 'd'

yield 'e'

except ValueError:

print('触发“ValueError"了')

except TypeError:

print('触发“TypeError"了')

g=my_generator()

print(next(g))

print(next(g))

print('-------------------------')

print(g.throw(ValueError))

print('-------------------------')

print(next(g))

print(next(g))

print('-------------------------')

print(g挥洒自如江一龙.throw(TypeError))

print('-------------------------')

print(next(g))

'''运转成果为:

a

b

-------------------------

触发“ValueError"了

a

-------------------------

b

c

-------------------------

触发“TypeError"了

a

-------------------------

b

'''

解说:

呈现这样的成果是不是很意外?它和上面的那个比如只要一个while只差,为什么成果差这么多,解说如下:

首要print(next(g))两次:会输出a、b,并停留在c之前。

然后由于履行了g.throw(ValueError),所以会越过一切后续的try句子,也便是说yield '西南大学研究生院,Python协程一从generator和yield表达式说起,桐城c'、yield 'd'、yield 'e'不会被执努房有术行,然后进入到except句子,打印出 触发“ValueError"了。然后再次进入到while句子部分,耗费一个yield,此刻由于是从头进入的while,小号的仍然是榜首个yield 'a',所以会输出a。实际上这儿的a也便是g.throw()的回来值,由于它回来的是下一个迭代的数;

然后在print(next(g))两次,会履行yield b’、yield 'c’句子,打印出b、c,并停留在履行完该句子后的方位,即yield 'd'之前。

然后再g.throw(TypeError):会跳出try句子,然后后边的d,e不会被履行,下次自一次进入while,仍然打印出a。

最终,履行了一次print(next(g)),打印出b。

06

生成器的发动与封闭close

生成器的发动与封闭close

6.1 生成器的发动

运用close()办法手动封闭生成器函数,后边的调用会直接回来StopIteration反常

这儿所评论的发动不是运用for循环迭代,咱们在运用for循环迭代的时分或许没有去考虑“发动”与“封闭”这些工作,这儿指的是运用next()内置办法一个一个迭代的景象。在榜首次迭代的时分,一定要先发动生成器,发动的两种办法为:

榜首:直接运用next(g),这会直接开端迭代榜首个元素(引荐运用这个发动)

第二:运用g.send(None)进行发动,留意榜首次发动的时分只能传入None,假如传入其他具体的指则会报错哦!

def my_g西南大学研究生院,Python协程一从generator和yield表达式说起,桐城enerator():

yield 1

yield 2

yield 3

yield 4

g = my_generator()

g.send(None) #榜首次发动,原本榜首次应该迭代的1,这儿被替代了,可是send(None)会回来1

print(next(g))

print(next(g))

print(next(g蜀龙路五期最新进展))

'''运转成果为:

2

3

4

'''

生成器的发动与封闭close

6.2 生成器的封闭

假如一个生成器被半途封闭之后,在此调用next()办法,则会显现过错,如下:

def my_generator():

yield 1

yield 2

yield 3

yield 4

g = my_generator()

print(next(g))

print(next(g))

g.close()

print(next(g社区福利)) #在此处会显现过错

print(next(g))

'''运转成果为:

1

2

显现StopIteration

'''

07

生成器的停止迭代——StopIteration

前面讲的手动封闭生成器,运用close()办法,后边的迭代或抛出StopIteration反常。别的

在一个生成器中,假如没有return,则默许履行到函数完毕时回来刘勋德StopIteration;

def g1():

yield 1

g=g1()

next(g) #榜首次调用next(g)时,会在履行完yield句子后挂起,所以此刻程序并没有履行完毕。

next(g) #程序企图从yield句子的下一条句子开端履行,发现现已到了结束,所以抛出StopIteration反常。

'''运转成果为:中北大学个人门户

1

Traceback (most recent call last):

File "", line 1, in

StopIteration

'''

假如遇到return,假如在履行过程中 return,则直接抛出 StopIteration 停止迭代。

def g2():

yield 'a'

return

yield 'b'

g=g2()

next(g) #程序停留在履行完yield 'a'句子后的方位。

next(g) #程序发现下一条句子是return,所以抛出StopIteration反常,这样yield 'b'句子永久也不会履行。

'''运转成果为:

a

b

Traceback (most recent call last):

File "", line 1, in

StopIter蔡菲凡ation

'''

假如在return后回来一个值,那么这个值为StopIteration反常的阐明,不是程序的回来值。

def g3():

yield 'a万世战魂'

return '这是过错阐明'

yield 'b' #有一些编辑器会提示过错,此处为unreachable code,即不行抵达的代码

g=g3()

next(g)

next(g)

'''运转成果为:

a

Traceback (most recent call last):

File "", line 1, in

StopIteration: 这是过错阐明

'''

留意:生成器没有办法运用return来回来值。由于return回来的那个值是经过StopIteration的反常信息回来的,所以我没办法直接获取这个return回来的值。

当然上面所说的无法获取return回来值,咱们指的是没有办法经过result=g3()这种方式获取return的回来值。实际上仍是有相依欧诺个的手法获取这个return的值的,有两种办法:

办法一:运用后边的yield 木加见from 句子(下文在解说)

办法二:由于return回来的值是作为StopIteration的一个value特点存在的,StopIte张玉贞国语版全集ration本质上是一个类,所以能够经过拜访它的value特点获取这个return回来的值。运用下面的代码:

def g3():

yield 'a'

return '这是过错阐明'

yield 'b'

g=g3()

try人交:

print(next(g)) #a

print(next(新泰数字电影院g)) #触发反常

except StopIteration as exc:

result=exc.value

print(result)

'''运转成果为:

a

这是过错阐明

'''

总结:上面具体解说了关于python生成器的各个办法的具体运用状况,还没有正式进入到协程的部分,关于协程的具体解说将会在后续的系列文章中逐步解说,有爱好的小伙伴能够重视一下

Python学习道路和PDF电子书:

Python 全系列

榜首阶段:Python入门第二阶段:Python 深化与进步第三阶段:Python 网络与并发编程第四阶段:数据库编程根底第五阶段:Linux 环境编程根底第六阶段:Python 中心特性第七阶段:网页编程根底第八阶段:Python_Django 结构第九阶段:Pyfylgython_Tornado 结构第十阶段:Python_大型电商项目第十一阶段:Python 爬虫开发第十二阶段:面试和成功求职的秘技第十三阶段:入职后快速成长到CTO

(学习道路配套视频和PDF电子书)只需重视谌天舒转发文章私信小编(学习)就可拿到了!

点击展开全文

上一篇:

下一篇:

相关推荐