文档章节

python yield

极光火狐狸
 极光火狐狸
发布于 2015/11/10 15:44
字数 1211
阅读 98
收藏 5

什么是yield?

    yield有点类似于continue和return的结合, 代码的运行的过程方式都是一样的, 执行完一行之后运行下一行.

    在continue里面(请查看注意事项里面的2说明), 当执行的代码遇到continue的时候, 就不会再执行后续的语句, 而是跳到循环的头部位置进行下一次循环.

    在yield里面(请查看注意事项里面的1说明), 当执行的代码遇到yield的时候, 就不会再执行后续的语句, 而是跳出函数, 并返回结果.

 

yield运行原理

场景1: 最简单的yield代码样例

[root@localhost ~]# vim test_yield.py
#!/bin/env python
# -.- coding:utf-8 -.-
def hello(n):
    print 'yield之前'
    n += 1
    yield n
    print 'yield之后'
    n *= 2
    print n
 
s = hello(100)
print '运行第一个next'
s.next()

# 运行结果

[root@localhost ~]# python test_yield.py
运行第一个next
yield之前                      # 这个是输出结果.

总结: 通过这段代码可以看出来, 当执行的代码遇到yield的时候, 就不会再执行后续的语句, 而是跳出函数, 并返回结果.

 

场景2: 在场景1代码的例子上增加一个next(), 观察输出结果

[root@localhost ~]# vim test_yield.py
#!/bin/env python
# -.- coding:utf-8 -.-
def hello(n):
    print 'yield之前'
    n += 1
    yield n
    print 'yield之后'
    n *= 2
    print n
s = hello(100)
print '运行第一个next'
s.next()
 
print '\n\n运行第二个next' # 增加了这行代码
s.next()                  # 增加了这行代码

# 运行结果

[root@localhost ~]# python test_yield.py
运行第一个next
yield之前
运行第二个next
yield之后
202
Traceback (most recent call last):
  File "test_yield.py", line 34, in <module>
    s.next()
StopIteration

总结: 通过这段代码可以看出来, 当第二次运行next的时候, 其实是先运行第一次阻断后面的内容, 然后才报错, 这个报错是因为没有next了.

 

场景3: 其实可以把yield理解为暂停功能.

#!/bin/env python
# -.- coding:utf-8 -.-
def get_time():
    from datetime import datetime
    return datetime.now()
 
def hello(n):
    for i in xrange(n):
        print 'yield之前',
        print get_time()
        yield n
        print 'yield之后',
        print get_time()
 
s = hello(5)
print '运行第一个next'
s.next()
 
print '\n\n运行第二个next'
s.next()
 
print '\n\n运行第三次next'
s.next()
 
print '\n\n运行第四次next'
s.next()
 
print '\n\n运行第五次next'
s.next()
 
print '\n\n运行第六次next'
s.next()

# 运行结果

[root@localhost ~]# python test_yield.py 
运行第一个next
yield之前 2015-11-10 01:58:31.753858
 
 
运行第二个next
yield之后 2015-11-10 01:58:31.753908
yield之前 2015-11-10 01:58:31.753941
 
 
运行第三次next
yield之后 2015-11-10 01:58:31.753952
yield之前 2015-11-10 01:58:31.753957
 
 
运行第四次next
yield之后 2015-11-10 01:58:31.753965
yield之前 2015-11-10 01:58:31.753970
 
 
运行第五次next
yield之后 2015-11-10 01:58:31.753977
yield之前 2015-11-10 01:58:31.753982
 
 
运行第六次next
yield之后 2015-11-10 01:58:31.753989
Traceback (most recent call last):
  File "test_yield.py", line 67, in <module>
    s.next()
StopIteration

总结: 通过上面这三个代码应该就已经大概知道yield是什么东西, 也知道它是怎么运作的了, 但是它老是报StopIteration这个错误.

 

场景4: 利用遍历来规避StopIteration错误

[root@localhost ~]# vim test_yield.py
#!/bin/env python
# -.- coding:utf-8 -.-
def get_time():
    from datetime import datetime
    return datetime.now()
 
def hello(n):
    for i in xrange(n):
        print 'yield之前',
        print get_time()
        yield n
        print 'yield之后',
        print get_time()
 
counter = 1
for i in hello(5):
    print '\n\n运行第%s个next' % counter
    counter += 1

# 运行结果

[root@localhost ~]# python test_yield.py
yield之前 2015-11-10 02:03:50.148205
 
 
运行第1个next
yield之后 2015-11-10 02:03:50.148256
yield之前 2015-11-10 02:03:50.148265
 
 
运行第2个next
yield之后 2015-11-10 02:03:50.148274
yield之前 2015-11-10 02:03:50.148279
 
 
运行第3个next
yield之后 2015-11-10 02:03:50.148286
yield之前 2015-11-10 02:03:50.148291
 
 
运行第4个next
yield之后 2015-11-10 02:03:50.148299
yield之前 2015-11-10 02:03:50.148304
 
 
运行第5个next
yield之后 2015-11-10 02:03:50.148311

 

场景5: yield传参

[root@localhost ~]# vim multi-para_yield.py
#!/bin/env python
# -.- coding:utf-8 -.-
 
def hello(n):
    for i in xrange(n):
        print 'yield之前'
        new_value = yield i
        print 'yield之后'
        print 'new_value is:', new_value, i
 
s = hello(3)
print '\n\n第一次next'
s.next()
print '\n\n第二次next'
s.next()
print '\n\n第三次next(其实是send)'
s.send('hello world!')

# 运行结果

[root@localhost ~]# python multi-para_yield.py 
 
 
第一次next
yield之前
 
 
第二次next
yield之后
new_value is: None 0
yield之前
 
 
第三次next(其实是send)
yield之后
new_value is: hello world! 1            # 重点在这里, 会发现传参和自身变量截然不同, 这应该是yield传参的固有写法.
yield之前

 

注意事项:

    1. yield只能写在函数里面, 不能写在函数外面.

    2. continue只能运行在循环语句中.

    3. 无法使用try来规避调用next时报的StopIteration错误.

    4. yield对象所有属性:

['__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']

 

© 著作权归作者所有

共有 人打赏支持
极光火狐狸
粉丝 11
博文 29
码字总数 14739
作品 0
普陀
私信 提问
从python协程理解tornado异步

博客原文地址:http://www.v2steve.com/2015/05/31/python/pytornadoasync/ 刚接触tornado时候最疑惑的问题就是tornado.gen.coroutine是怎么实现的。如何在代码中用同步格式实现异步效果。看...

__Steve__
2015/05/31
0
0
Python yield 使用浅析(转载)

Python yield 使用浅析 转载http://www.ibm.com/developerworks/cn/opensource/os-cn-python-yield/ 以下是理解归纳 如何生成斐波那契數列 def fab(max): 执行 fab(5) 问题是print太多了 解决...

okker
2013/12/16
0
0
Iterator, Generator 与 Yield

Iterator Iterator(迭代器) 是一种常见的对象,它允许调用者方便的遍历该对象中的元素,广泛的运用于多种编程语言,如 Python, Java 和 Ruby 等。以 Python 为例,Iterator 需要实现两种方法...

koala bear
2016/10/18
0
0
Python3+迭代器与生成器

转载Python3 迭代器与生成器 迭代器 迭代是Python最强大的功能之一,是访问集合元素的一种方式。 迭代器是一个可以记住遍历的位置的对象。 迭代器对象从集合的第一个元素开始访问,直到所有的...

xinet
2017/08/12
0
0
python学习笔记—yield生成器

python学习笔记—yield生成器 1.生成器 yield可以返回当前的参数的值。但是yield记录了当前运行的位置,下次调用的时候会重新从这个位置开始运行。还有就是调用了yield的函数,可以在一次调用...

Scanf_Love
2014/09/01
0
0

没有更多内容

加载失败,请刷新页面

加载更多

nacos之springboot

本地操作系统:ubuntu18,我使用docker的方式启动nacos服务 docker image方式启动nacos 在docker hub上可以搜到nacos-server List-1.1 拉去最新的版本 mjduan@mjduan-ubuntu:/opt/software$ ...

克虏伯
27分钟前
2
0
指针数组和数组指针的区别

这两个名字不同当然所代表的意思也就不同。我刚开始看到这就吓到了,主要是中文太博大精深了,整这样的简称太专业了,把人都绕晕了。从英文解释或中文全称看就比较容易理解。 指针数组:arr...

天王盖地虎626
59分钟前
3
0
Qt那些事0.0.18

今天要记一下Qt中的Resource。自我感觉理解的不错,但是还会难免有谬误,在日后有可能会更新,也有可能不会。 小声的念叨一句,女人心,海底针。 今天就直接跳过了关于QML在qrc文件中的介绍,...

Ev4n
今天
2
0
深入解析js的作用域、预解析机制

虽然,ES6在我们工作中应用得越来越广泛,但是还是很多项目保留着ES5的写法,所以,今天,带着大家重新巩固下ES5下的作用域及预解析机制。 概念: 作用域:域,指的是一个空间、范围、区域,...

前端攻城老湿
今天
2
0
Spring Cloud Feign - 声明式 REST Client

1、Feign是什么 声明式REST client,来自NetFlix。 允许你编写无实现代码调用REST services 替换RestTemplate(甚至更简单) Spring Cloud 为使用Feign提供了包装器 2、怎样使用Feign 对比:...

Benz001
今天
8
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部