设为首页 收藏本站
查看: 1397|回复: 0

[经验分享] Python——对生成器的一点小测试

[复制链接]

尚未签到

发表于 2018-8-7 08:14:37 | 显示全部楼层 |阅读模式
"""  
1、生成器就是对象
  
2、每次调用next()方法时就返回一个值,直到抛出StopIteration异常
  
3、如何创建生成器?很简单,只需写一个普通的函数并包含yield语句,而不是return语句,因此,python会自动将这个函数标记为生成器
  
4、yield语句的主要作用是和return语句一样返回一个值,但最重要也是最需要明白的是,yield语句返回值后,解释器会保存对栈的引用
  
    它将被用来在下一次调用next()时回复函数的执行
  
"""
  

  
#创建一个生成器
  
def mygen():
  
    yield 1
  
    yield 2
  
    yield "a"
  
    yield "b"
  

  
# print(mygen()) #此刻,打印出来的是一个生成器对象
  
# g = mygen()
  
# print(next(g))
  
# print(next(g))
  
# print(next(g))
  
# print(next(g))
  
#print(next(g)) #已结到达最后一个数据了,如果还继续打印则抛出StopIteration异常
  

  
#检查一个函数是否是一个生成器,是的话返回true,不是的话返回false
  
# import inspect
  
# ret = inspect.isgeneratorfunction(mygen)
  
# print(ret)
  

  
#查看生成器的当前状态
  
"""
  
有下面几种状态:
  
    1、GEN_CREATED:正在等待第一次被执行
  
    2、GEN_RUNNING:当前正在被解析器执行
  
    3、GEN_SUSPENDED:等待被next()调用唤醒
  
    4、GEN_CLOSED:已结结束运行
  
"""
  
#测试一下,是如何查看这些状态的
  
import inspect
  
def mygen2():
  
    yield 1
  
gens = mygen2()
  
print(inspect.getgeneratorstate(gens)) #第一次查看状态是,GEN_CREATED(正在等待第一次被执行)
  
print(next(gens)) #通过next()调用一次
  
print(inspect.getgeneratorstate(gens)) #此时的状态是GEN_SUSPENDED(等待被next()调用唤醒)
  
try:
  
    print(next(gens)) #再next()一次的话,因没有值了所以引发了一个StopIteration异常
  
except StopIteration:
  
    pass
  
print(inspect.getgeneratorstate(gens)) #那么,它的状态是GEN_CLOSED(已结结束运行)
  

  
#那么生成器的应用场景是啥?看个例子
  
"""
  
在我的ubuntu操作系统环境
  
root@udesk:~# ulimit -v 131072 #限制运行内存在128M
  
root@udesk:~# python3
  
Python 3.5.2 (default, Nov 23 2017, 16:37:01)
  
[GCC 5.4.0 20160609] on linux
  
Type "help", "copyright", "credits" or "license" for more information.
  
>>> a = list(range(10000000))
  
Traceback (most recent call last):
  
  File &quot;<stdin>&quot;, line 1, in <module>
  
MemoryError #内存错误
  
>>>
  

  
#用生成器的方式试试
  
>>> for v in range(10000000):
  
...     if v == 50000:
  
...         print(&quot;found ok&quot;)
  
...         break
  
...
  
found ok
  

  
奇怪的是,我左看右看,看着都不像是生成器啊!
  
原因是:
  
    在python3中,range()函数会返回生成器,也就是说返回的是一个可迭代对象(这点一定要记住)
  
    所以,我只需要第50000个数字,生成器仅仅只会生成50000个数字,而不是像刚才
  
    那么样试图要生成10000000个数字,导致把内存给撑爆了
  

  
我在python2环境中测试了下,那么需要注意的问题有:
  
>>> xrange(10000000) #python2中xrange是用于返回生成器(也就是说不会马上生成,用的时候才会即时的生成)
  
xrange(10000000)
  
>>> range(10000000) #range获取生成器(也就是说会马上生成数字)
  
Traceback (most recent call last):
  
  File &quot;<stdin>&quot;, line 1, in <module>
  
MemoryError
  

  
注意了:在python3中去除掉了xrange()函数,仅有range,python3中的range就是返回生成器
  

  
简单总结,用专家说的话就是:
  
    生成器运行通过即时生成的值以极少的内存消耗来应对大规模的数据集和循环处理
  
    任何时候想要操作大规模数据,生成器都可以帮助确保有效地对数据进行处理
  
&quot;&quot;&quot;
  

  
#再看一个例子
  
#一般的写法
  
def addlist(alist):
  
    r = []
  
    for i in alist:
  
        r.append(i + 1)
  
    return r
  
ret = addlist([1,2,3,4,5])
  
print(ret)
  

  
#通过yield的写法
  
def yieldlist(alist):
  
    for i in alist:
  
        yield i + 1
  
ret1 = addlist([1,2,3,4,5])
  
print(ret1)
  
#结果都是一样,那么数据量小看不出啥效果,要不你搞1000万条数据你再试试?效果就立马出来了
  

  
#最后关于send和next
  
&quot;&quot;&quot;
  
send()与next()的区别在于send可以传递参数给yield表达式,
  
这时传递的参数会作为yield表达式的值,而yield的参数是返回给调用者的值。
  
初始调用时必须先next()或send(None),否则会报错。
  
&quot;&quot;&quot;
  
#下面看个例子:我想实现生产一些IP地址,并发送给另外一个函数干活
  
def jobs():
  
    while True:
  
        ip = yield #yiend接收send发送过来的ip
  
        print(&quot;ssh connection:{},Start power off...&quot;.format(ip))  #开始干活
  

  
#生产IP地址
  
def production_ip():
  
    j = jobs()
  
    next(j) #初始调用时必须先next()
  
    for i in range(10):
  
        ip = &quot;192.168.89.{0}&quot;.format(i) #生产IP地址
  
        j.send(ip) #将IP地址发生给干活的函数jobs
  

  
production_ip()

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.iyunv.com/thread-547903-1-1.html 上篇帖子: Python网络编程之socket 下篇帖子: Python第五周 学习笔记(2)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表