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

[经验分享] Python的迭代器与生成器

[复制链接]

尚未签到

发表于 2018-8-14 09:10:01 | 显示全部楼层 |阅读模式
迭代器
  为了更好的理解迭代器和生成,我们需要简单的回顾一下迭代器协议的概念。
迭代器协议
  1.迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代 (只能往后走不能往前退)
  2.可迭代对象:实现了迭代器协议的对象(如何实现:对象内部定义一个__iter__()方法)
  3.协议是一种约定,可迭代对象实现了迭代器协议,python的内部工具(如for循环,sum,min,max函数等)使用迭代器协议访问对象。
for循环
  for循环的本质:循环所有对象,全都是使用迭代器协议。
  for循环就是基于迭代器协议提供了一个统一的可以遍历所有对象的方法,即在遍历之前,先调用对象的__iter__方法将其转换成一个迭代器,然后使用迭代器协议去实现循环访问,这样所有的对象就都可以通过for循环来遍历了,
  列表,字符串,元组,字典,集合,文件对象等本质上来说都不是可迭代对象,在使用for循环的时候内部是先调用他们内部的_iter_方法,使他们变成了可迭代对象,然后在使用可迭代对象的_next_方法依次循环元素,当元素循环完时,会触发StopIteration异常,for循环会捕捉到这种异常,终止迭代。
  如访问一个list,可以使用平时习惯的写法:
#for循环访问#for循环l本质就是遵循迭代器协议的访问方式,先调用diedai_l=l.__iter__()方法,或者直接diedai_l=iter(l),然后依次执行diedai_l.next(),直到for循环捕捉到StopIteration终止循环li = [1,2,3,4]for i in li:#li_iter = li._iter_()  
    print(i)#li_iter._next_
  也可以直接使用迭代器访问:
DSC0000.gif

#迭代器协议访问li = [1,2,3,4]  
f = li.__iter__()#第一步,先通过内部的_iter_方法,先把对象变成可迭代对象print(f.__next__())#对可迭代对象用_next_方法取值print(f.__next__())print(f.__next__())print(f.__next__())print(f.__next__())#StopIteration,超出边界会报错

生成器
  在介绍生成器之前,先简单介绍一下列表生成式
列表生成式
  列表生成式即List Comprehensions,是Python内置的非常简单却强大的可以用来创建list的生成式。
  举个例子,要生成list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]可以用range(1, 11):
>>> range(1, 11)  
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  列表生成式可以代替循环在编程中偷懒,如生成[1x1, 2x2, 3x3, ..., 10x10]怎么做?可以用普通的循环,也可以用列表生成器完成,如下:
>>> [x * x for x in range(1, 11)]  
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
  通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
  所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器(Generator)。
创建生成器的两种方法
  第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:
>>> L = [x * x for x in range(10)]>>> L  
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]>>> g = (x * x for x in range(10))>>> g<generator object <genexpr> at 0x104feab40>
  L是一个list,而g是一个generator,如果想要访问生成器中元素,需要用生成器的next()方法。或者利用for循环,因为generator也是一个可迭代的对象。
  第二种方法需要借助“yield”,以计算斐波那契数列为例,展示一个函数如何变成生成器,直接上代码:
def fib(max):  
    n, a, b = 0, 0, 1    while n < max:        print b
  
        a, b = b, a + b
  
        n = n + 1
  这是普通的函数,将print改为yield即为生成器:
def fib(max):  
    n, a, b = 0, 0, 1    while n < max:        yield b
  
        a, b = b, a + b
  
        n = n + 1
  函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。再举一个简单的例子,定义generator,返回1,3,5:

>>> def odd():  
...     print 'step 1'...     yield 1...     print 'step 2'...     yield 3...     print 'step 3'...     yield 5...>>> o = odd()>>> o.next()
  
step 1
  
1
  
>>> o.next()
  
step 2
  
3
  
>>> o.next()
  
step 3
  
5
  
>>> o.next()
  
Traceback (most recent call last):
  
  File "<stdin>", line 1, in <module>StopIteration

  可以看到,odd不是普通函数,而是generator,在执行过程中,遇到yield就中断,下次又继续执行。执行3次yield后,已经没有yield可以执行了,所以,第4次调用next()就报错。
  同样,在获取元素时,大多数时候运用for循环。

运维网声明 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.yunweiku.com/thread-551444-1-1.html 上篇帖子: 5 Python 关于除法运算 下篇帖子: python+robot framework接口自动化测试
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

扫描微信二维码查看详情

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


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


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


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



合作伙伴: 青云cloud

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