1. # 迭代器和生成器
  2. # 迭代器:
  3. # 双下方法 : 很少直接调用的方法。一般情况下,是通过其他语法触发的
  4. # 可迭代的 —— 可迭代协议 含有__iter__的方法('__iter__' in dir(数据))
  5. # 可迭代的一定可以被for循环
  6. # 迭代器协议: 含有__iter__和__next__方法
  7. # 迭代器一定可迭代,可迭代的通过调用iter()方法就能得到一个迭代器
  8. # 迭代器的特点:
  9. # 很方便使用,且只能取所有的数据取一次
  10. # 节省内存空间
  11.  
  12. # 生成器
  13. # 生成器的本质就是迭代器
  14. # 生成器的表现形式
  15. # 生成器函数
  16. # 生成器表达式
  17. # 生成器函数:
  18. #含有yield关键字的函数就是生成器函数
  19. #特点:
  20. #调用函数的之后函数不执行,返回一个生成器
  21. #每次调用next方法的时候会取到一个值
  22. #直到取完最后一个,在执行next会报错
  1. #!/usr/bin/env python
  2. # coding:utf-8
  3.  
  4. # 迭代器即迭代的工具,那什么是迭代呢?
  5. # 迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的结果都是下一次迭代的初始值
  6. # while True: # 只是单纯地重复,因而不是迭代
  7. # print('===>')
  8.  
  9. l = [1, 2, 3]
  10. count = 0
  11. while count < len(l): # 迭代
  12. print(l[count])
  13. count += 1
  14.  
  15. ### for 循环就是基于迭代器协议去工作。
  16. # a = l.__iter__() # 转为可迭代对象
  17. # print(a.__next__()) # 使用可迭代对象的next方法
  18. # print(a.__next__())
  19. # print(a.__next__())
  20.  
  21. # for i in l:
  22. # print(i)
  23.  
  24. indx = 0
  25. while indx < len(l):
  26. print(l[indx])
  27. indx += 1
  28.  
  29. '''
  30. #1、为何要有迭代器?
  31. 对于序列类型:字符串、列表、元组,我们可以使用索引的方式迭代取出其包含的元素。
  32. 但对于字典、集合、文件等类型是没有索引的,若还想取出其内部包含的元素,则必须找出一种不依赖于索引的迭代方式,这就是迭代器
  33.  
  34. #2、什么是可迭代对象?
  35. 可迭代对象指的是内置有__iter__方法的对象,即obj.__iter__,如下
  36. 'hello'.__iter__
  37. (1,2,3).__iter__
  38. [1,2,3].__iter__
  39. {'a':1}.__iter__
  40. {'a','b'}.__iter__
  41. open('a.txt').__iter__
  42.  
  43. #3、什么是迭代器对象?
  44. 可迭代对象执行obj.__iter__()得到的结果就是迭代器对象
  45. 而迭代器对象指的是即内置有__iter__又内置有__next__方法的对象
  46.  
  47. 文件类型是迭代器对象
  48. open('a.txt').__iter__()
  49. open('a.txt').__next__()
  50.  
  51. #4、注意:
  52. 迭代器对象一定是可迭代对象,而可迭代对象不一定是迭代器对象
  53. '''
  54.  
  55. dic = {'a': 11, 'b': 22, 'c': 33}
  56. iter_dic = dic.__iter__() # 得到迭代器对象,迭代器对象即有__iter__又有__next__,但是:迭代器.__iter__()得到的仍然是迭代器本身
  57. iter_dic.__iter__() is iter_dic # True
  58. # print(iter_dic.__iter__() is iter_dic) # True
  59.  
  60. """
  61. print(iter_dic.__next__()) # 等同于next(iter_dic)
  62. print(iter_dic.__next__()) # 等同于next(iter_dic)
  63. print(iter_dic.__next__()) # 等同于next(iter_dic)
  64. # print(iter_dic.__next__()) #抛出异常StopIteration,或者说结束标志
  65.  
  66. # 有了迭代器,我们就可以不依赖索引迭代取值了
  67. """
  68. iter_dic = dic.__iter__()
  69. while 1:
  70. try:
  71. k = next(iter_dic)
  72. print(dic[k])
  73. except StopIteration:
  74. break
  75.  
  76. # 这么写太丑陋了,需要我们自己捕捉异常,控制next,python这么牛逼,能不能帮我解决呢?能,请看 for 循环
  77.  
  78. #基于for循环,我们可以完全不再依赖索引去取值了
  79. dic={'a':111,'b':222,'c':333}
  80. for k in dic:
  81. print(dic[k])
  82.  
  83. '''
  84. #for循环的工作原理
  85. #1:执行in后对象的dic.__iter__()方法,得到一个迭代器对象iter_dic
  86. #2: 执行next(iter_dic),将得到的值赋值给k,然后执行循环体代码
  87. #3: 重复过程2,直到捕捉到异常StopIteration,结束循环
  88. '''
  1. #!/usr/bin/env python
  2. # coding:utf-8
  3.  
  4. # 生成器函数, 函数内部有yield ,保留函数的生成状态
  5. def test():
  6. yield 1
  7. yield 2
  8. yield 3 # 相当于return,但是却可以多次
  9. g = test()
  10. print(g)
  11. print(g.__next__()) #
  12. print(g.__next__()) #
  13.  
  14. ### 三元操作符
  15. name = 'alex'
  16. res = 'sb' if name =='alex' else 'kkk'
  17. print(res)
  18.  
  19. ### 列表解析l
  20. # egg_list=[]
  21. # for i in range(10):
  22. # egg_list.append('鸡蛋%s' %i)
  23. # print(egg_list)
  24.  
  25. lis = ['鸡蛋%s' %i for i in range(10)] # 等同于上面的过程。
  26. lis2 = ['鸡蛋%s' %i for i in range(20) if i >10]
  27. lis3 = ['鸡蛋%s' %i for i in range(10) if i > 5] #
  28. print(lis)
  29. print(lis2)
  30. print(lis3)
  31.  
  32. ## 例:找到嵌套列表中名字含有两个'e'的所有名字
  33. names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
  34. ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
  35.  
  36. list3 = [name for lst in names for name in lst if name.count('e') >= 2]
  37. print(list3)
  38.  
  39. ## 生成器表达式
  40. ## 优点:省内存,一次只产生一个值在内存中 因为生成器表达式是基于迭代器 __next__ 方法取值 .
  41. ## 把列表推导式的 [] 换成 () 就是生成器表达式
  42. lise = ('鸡蛋%s' %i for i in range(10))
  43. print(lise)
  44. print(lise.__next__())
  45. print(lise.__next__())
  46. print(next(lise)) # next 就是调用了内置的 __next__
  47.  
  48. # sum 里面可以直接写生成器表达式,因为就是调用了可迭代对象的__next__
  49. print(sum(i for i in range(10000001))) # 一千万
  1. #!/usr/bin/env python
  2. # coding:utf-8
  3.  
  4. import time
  5.  
  6. def test():
  7. print('start 1st...')
  8. yield 'first generation.' # 遇到yield就返回结果,并保留运行状态。
  9. time.sleep(3)
  10. print('start 2nd___')
  11. yield 'second generation..'
  12. time.sleep(3)
  13. print('start 3rd')
  14. yield 'third generation...'
  15.  
  16. a = test()
  17. print(a.__next__()) # 遇到yield就返回结果,并保留运行状态。
  18. print(a.__next__()) # 继续上次的运行状态往下执行。
  19. print(a.__next__())
  20.  
  21. """
  22. 1. 迭代器协议: 对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就StopIteration异常,以终止迭代
  23. 2. 可迭代对象: 实现了迭代器协议的对象(如何实现:对象内部定义一个__iter__()方法)
  24. 3. 生成器就是自动实现了迭代器协议.
  25.  
  26. """

假设有个字典格式的文件people 内容如下:

  1. {'name':'上海','population':999}
    {'name':'杭州','population':8888}
    {'name':'苏州','population':7767}
    {'name':'无锡','population':23456}
  1. #!/usr/bin/env python
  2. # coding:utf-8
  3.  
  4. ### 把函数做成生成器的好处是,next一次取一个值,立刻就可以操作.不必等到下一个值产生.
  5. ### 得到一个值立马可以处理, next中可以加一些操作.
  6. def baozi():
  7. for i in range(100):
  8. print("正在生产包子...")
  9. yield '一笼包子%s' %i
  10. print('收钱.')
  11.  
  12. a = baozi()
  13. bz1=a.__next__()
  14. print(bz1)
  15. bz2=a.__next__()
  16. print(bz2)
  17.  
  18. ### 母鸡下蛋的传说:
  19. def xiadan():
  20. for i in range(100):
  21. yield '鸡蛋%s' %i
  22.  
  23. alex = xiadan()
  24. print('路人甲获得%s' %alex.__next__())
  25. print('路人乙获得%s' %alex.__next__())
  26.  
  27. ## 生成器也可以被 for 循环
  28. # for i in alex:
  29. # print(i)
  30.  
  31. # import this # 保证代码可读性的前提下,尽量精简
  32.  
  33. ## 取各地区人口的示例:
  34. def get_population():
  35. with open('people','r',encoding='utf-8') as f:
  36. for i in f:
  37. yield eval(i)
  38.  
  39. g = get_population() # 得到生成器
  40. all_pop = sum(i['population'] for i in g) ## 求和总人口
  41. print(all_pop)
  42.  
  43. ## 如果使用next来取得列表, 也就没有必要了.没有发挥生成器的优势.

一个生动的例子: 生产者消费者模型:

  1. #!/usr/bin/env python
  2. # coding:utf-8
  3.  
  4. import time
  5.  
  6. # def producer():
  7. # ret=[]
  8. # for i in range(100):
  9. # time.sleep(0.01)
  10. # ret.append('包子%s' %i)
  11. #
  12. # return ret
  13. #
  14. # def consumer(res):
  15. # for idx, things in enumerate(res):
  16. # time.sleep(0.1)
  17. # print('第%s个人,吃了%s' %(idx,things))
  18. #
  19. #
  20. # res = producer()
  21. # consumer(res)
  22.  
  23. #### 生产者 消费者模型
  24. #### 使用生成器改写上面的程序,实现并发:
  25.  
  26. def consumer(name):
  27. print('我是%s, 我要开始吃包子了.' % name)
  28. while True:
  29. baozi=yield
  30. time.sleep(0.5)
  31. print('%s 很开心地把 %s 吃掉了.' %(name,baozi))
  32.  
  33. def producer():
  34. c1 = consumer('Tom') # 调用上面的生成器函数
  35. c1.__next__()
  36. for i in range(10):
  37. time.sleep(0.5)
  38. c1.send('肉包子%s' %i) # 由send
  39.  
  40. producer()
  41. ## 单线程并发

python基础15上_迭代器_生成器的更多相关文章

  1. Py修行路 python基础 (十一)迭代器 与 生成器

    一.什么是迭代? 迭代通俗的讲就是一个遍历重复的过程. 维基百科中 迭代(Iteration) 的一个通用概念是:重复某个过程的行为,这个过程中的每次重复称为一次迭代.具体对应到Python编程中就是 ...

  2. Python 基础 内置函数 迭代器与生成器

    今天就来介绍一下内置函数和迭代器 .生成器相关的知识 一.内置函数:就是Python为我们提供的直接可以使用的函数. 简单介绍几个自己认为比较重要的 1.#1.eval函数:(可以把文件中每行中的数据 ...

  3. python基础(8)--迭代器、生成器、装饰器

    1.迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退.另外,迭代器的一大优 ...

  4. python基础(八)-迭代器与生成器

    一.迭代器 li=[1,2,3] f=li.__iter__() print(f) print(f.__next__()) print(f.__next__()) print(f.__next__() ...

  5. Python基础(8)迭代器、生成器

    一 什么是迭代 1 重复 2 下一次重复是基于上一次的结果 # while True: # cmd=input('>>: ') # print(cmd) # l=['a','b','c', ...

  6. 2015/9/19 Python基础(15):变量作用域及生成器

    变量作用域标识符的作用域是定义为其声明的可应用范围,或者即是我们所说的变量可见性.也就是,我们可以在程序的那个部分去访问一个制定的标识符.全局变量与局部变量定义在函数内的变量有局部作用域,在一个模块中 ...

  7. day18_文件处理_迭代器_生成器

    #!/usr/bin/env python # -*- coding:utf-8 -*- # ********************day18_文件处理_迭代器_生成器 ************** ...

  8. Python可迭代对象、迭代器和生成器

    Python可迭代对象.迭代器和生成器 python 函数 表达式 序列 count utf-8 云栖征文 python可迭代对象 python迭代器 python生成器 摘要: 8.1 可迭代对象( ...

  9. 十五. Python基础(15)--内置函数-1

    十五. Python基础(15)--内置函数-1 1 ● eval(), exec(), compile() 执行字符串数据类型的python代码 检测#import os 'import' in c ...

随机推荐

  1. [English] Time complexity wise this solution is the best among all

    Time complexity wise this solution is the best among all, we can do all operations in O(1) time. 时间复 ...

  2. 干货 | 揭秘如何增加listing多个类目节点

    流量是电商销售的必要因素,可以说,任何成功的电商平台都离不开流量.亚马逊listing优化做得好,不仅能提高产品的曝光率,还能提升转换率,而好的类目可以吸引大的流量.帮你快速爬升. 首先我们来了解一下 ...

  3. 异常:Error resolving template "xxx", template might not exist or might not be accessible...解决办法

    在开发环境下正常,但使用jar运行时,报错Error resolving template template might not exist or might not be accessible,意思 ...

  4. 安装weblogic

    附:wls1036_generic.jar 链接:https://pan.baidu.com/s/1W5g-SHeKL96yrOeDKJJoxw 提取码:vxft 注:以下安装步骤是一个前辈整理的,我 ...

  5. 判断PDF文件是否相同(通过二进制流判断)

    一.Java代码 1.将PDF转为字节流    /*     * @step     *  1.使用BufferedInputStream和FileInputStream从File指定的文件中读取内容 ...

  6. requests库/爬取zhihu表情包

    先学了requests库的一些基本操作,简单的爬了一下. 用到了requests.get()方法,就是以GET方式请求网页,得到一个Response对象.不加headers的话可能会400error所 ...

  7. VS2013 密钥– 所有版本

    Visual Studio Ultimate 2013 KEY(密钥):BWG7X-J98B3-W34RT-33B3R-JVYW9Visual Studio Premium 2013 KEY(密钥): ...

  8. Hive中数据的导入与导出

    最近在做一个小任务,将一个CDH平台中Hive的部分数据同步到另一个平台中.毕竟我也刚开始工作,在正式开始做之前,首先进行了一段时间的练习,下面的内容就是练习时写的文档中的内容.如果哪里有错误或者疏漏 ...

  9. asp.net 跨域访问

    摘自 https://docs.microsoft.com/en-us/aspnet/web-api/overview/security/enabling-cross-origin-requests- ...

  10. sql server中如何修改视图中的数据?

    sql server中如何修改视图中的数据? 我做个测试,视图的数据有标记字段时,如果是这种方式(0 as FlagState),是无法修改的 --创建视图语句 --- create view V_E ...