python基础15上_迭代器_生成器
- # 迭代器和生成器
- # 迭代器:
- # 双下方法 : 很少直接调用的方法。一般情况下,是通过其他语法触发的
- # 可迭代的 —— 可迭代协议 含有__iter__的方法('__iter__' in dir(数据))
- # 可迭代的一定可以被for循环
- # 迭代器协议: 含有__iter__和__next__方法
- # 迭代器一定可迭代,可迭代的通过调用iter()方法就能得到一个迭代器
- # 迭代器的特点:
- # 很方便使用,且只能取所有的数据取一次
- # 节省内存空间
- # 生成器
- # 生成器的本质就是迭代器
- # 生成器的表现形式
- # 生成器函数
- # 生成器表达式
- # 生成器函数:
- #含有yield关键字的函数就是生成器函数
- #特点:
- #调用函数的之后函数不执行,返回一个生成器
- #每次调用next方法的时候会取到一个值
- #直到取完最后一个,在执行next会报错
- #!/usr/bin/env python
- # coding:utf-8
- # 迭代器即迭代的工具,那什么是迭代呢?
- # 迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的结果都是下一次迭代的初始值
- # while True: # 只是单纯地重复,因而不是迭代
- # print('===>')
- l = [1, 2, 3]
- count = 0
- while count < len(l): # 迭代
- print(l[count])
- count += 1
- ### for 循环就是基于迭代器协议去工作。
- # a = l.__iter__() # 转为可迭代对象
- # print(a.__next__()) # 使用可迭代对象的next方法
- # print(a.__next__())
- # print(a.__next__())
- # for i in l:
- # print(i)
- indx = 0
- while indx < len(l):
- print(l[indx])
- indx += 1
- '''
- #1、为何要有迭代器?
- 对于序列类型:字符串、列表、元组,我们可以使用索引的方式迭代取出其包含的元素。
- 但对于字典、集合、文件等类型是没有索引的,若还想取出其内部包含的元素,则必须找出一种不依赖于索引的迭代方式,这就是迭代器
- #2、什么是可迭代对象?
- 可迭代对象指的是内置有__iter__方法的对象,即obj.__iter__,如下
- 'hello'.__iter__
- (1,2,3).__iter__
- [1,2,3].__iter__
- {'a':1}.__iter__
- {'a','b'}.__iter__
- open('a.txt').__iter__
- #3、什么是迭代器对象?
- 可迭代对象执行obj.__iter__()得到的结果就是迭代器对象
- 而迭代器对象指的是即内置有__iter__又内置有__next__方法的对象
- 文件类型是迭代器对象
- open('a.txt').__iter__()
- open('a.txt').__next__()
- #4、注意:
- 迭代器对象一定是可迭代对象,而可迭代对象不一定是迭代器对象
- '''
- dic = {'a': 11, 'b': 22, 'c': 33}
- iter_dic = dic.__iter__() # 得到迭代器对象,迭代器对象即有__iter__又有__next__,但是:迭代器.__iter__()得到的仍然是迭代器本身
- iter_dic.__iter__() is iter_dic # True
- # print(iter_dic.__iter__() is iter_dic) # True
- """
- print(iter_dic.__next__()) # 等同于next(iter_dic)
- print(iter_dic.__next__()) # 等同于next(iter_dic)
- print(iter_dic.__next__()) # 等同于next(iter_dic)
- # print(iter_dic.__next__()) #抛出异常StopIteration,或者说结束标志
- # 有了迭代器,我们就可以不依赖索引迭代取值了
- """
- iter_dic = dic.__iter__()
- while 1:
- try:
- k = next(iter_dic)
- print(dic[k])
- except StopIteration:
- break
- # 这么写太丑陋了,需要我们自己捕捉异常,控制next,python这么牛逼,能不能帮我解决呢?能,请看 for 循环
- #基于for循环,我们可以完全不再依赖索引去取值了
- dic={'a':111,'b':222,'c':333}
- for k in dic:
- print(dic[k])
- '''
- #for循环的工作原理
- #1:执行in后对象的dic.__iter__()方法,得到一个迭代器对象iter_dic
- #2: 执行next(iter_dic),将得到的值赋值给k,然后执行循环体代码
- #3: 重复过程2,直到捕捉到异常StopIteration,结束循环
- '''
- #!/usr/bin/env python
- # coding:utf-8
- # 生成器函数, 函数内部有yield ,保留函数的生成状态
- def test():
- yield 1
- yield 2
- yield 3 # 相当于return,但是却可以多次
- g = test()
- print(g)
- print(g.__next__()) #
- print(g.__next__()) #
- ### 三元操作符
- name = 'alex'
- res = 'sb' if name =='alex' else 'kkk'
- print(res)
- ### 列表解析l
- # egg_list=[]
- # for i in range(10):
- # egg_list.append('鸡蛋%s' %i)
- # print(egg_list)
- lis = ['鸡蛋%s' %i for i in range(10)] # 等同于上面的过程。
- lis2 = ['鸡蛋%s' %i for i in range(20) if i >10]
- lis3 = ['鸡蛋%s' %i for i in range(10) if i > 5] #
- print(lis)
- print(lis2)
- print(lis3)
- ## 例:找到嵌套列表中名字含有两个'e'的所有名字
- names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
- ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
- list3 = [name for lst in names for name in lst if name.count('e') >= 2]
- print(list3)
- ## 生成器表达式
- ## 优点:省内存,一次只产生一个值在内存中 因为生成器表达式是基于迭代器 __next__ 方法取值 .
- ## 把列表推导式的 [] 换成 () 就是生成器表达式
- lise = ('鸡蛋%s' %i for i in range(10))
- print(lise)
- print(lise.__next__())
- print(lise.__next__())
- print(next(lise)) # next 就是调用了内置的 __next__
- # sum 里面可以直接写生成器表达式,因为就是调用了可迭代对象的__next__
- print(sum(i for i in range(10000001))) # 一千万
- #!/usr/bin/env python
- # coding:utf-8
- import time
- def test():
- print('start 1st...')
- yield 'first generation.' # 遇到yield就返回结果,并保留运行状态。
- time.sleep(3)
- print('start 2nd___')
- yield 'second generation..'
- time.sleep(3)
- print('start 3rd')
- yield 'third generation...'
- a = test()
- print(a.__next__()) # 遇到yield就返回结果,并保留运行状态。
- print(a.__next__()) # 继续上次的运行状态往下执行。
- print(a.__next__())
- """
- 1. 迭代器协议: 对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就StopIteration异常,以终止迭代
- 2. 可迭代对象: 实现了迭代器协议的对象(如何实现:对象内部定义一个__iter__()方法)
- 3. 生成器就是自动实现了迭代器协议.
- """
假设有个字典格式的文件people 内容如下:
- {'name':'上海','population':999}
{'name':'杭州','population':8888}
{'name':'苏州','population':7767}
{'name':'无锡','population':23456}
- #!/usr/bin/env python
- # coding:utf-8
- ### 把函数做成生成器的好处是,next一次取一个值,立刻就可以操作.不必等到下一个值产生.
- ### 得到一个值立马可以处理, next中可以加一些操作.
- def baozi():
- for i in range(100):
- print("正在生产包子...")
- yield '一笼包子%s' %i
- print('收钱.')
- a = baozi()
- bz1=a.__next__()
- print(bz1)
- bz2=a.__next__()
- print(bz2)
- ### 母鸡下蛋的传说:
- def xiadan():
- for i in range(100):
- yield '鸡蛋%s' %i
- alex = xiadan()
- print('路人甲获得%s' %alex.__next__())
- print('路人乙获得%s' %alex.__next__())
- ## 生成器也可以被 for 循环
- # for i in alex:
- # print(i)
- # import this # 保证代码可读性的前提下,尽量精简
- ## 取各地区人口的示例:
- def get_population():
- with open('people','r',encoding='utf-8') as f:
- for i in f:
- yield eval(i)
- g = get_population() # 得到生成器
- all_pop = sum(i['population'] for i in g) ## 求和总人口
- print(all_pop)
- ## 如果使用next来取得列表, 也就没有必要了.没有发挥生成器的优势.
一个生动的例子: 生产者消费者模型:
- #!/usr/bin/env python
- # coding:utf-8
- import time
- # def producer():
- # ret=[]
- # for i in range(100):
- # time.sleep(0.01)
- # ret.append('包子%s' %i)
- #
- # return ret
- #
- # def consumer(res):
- # for idx, things in enumerate(res):
- # time.sleep(0.1)
- # print('第%s个人,吃了%s' %(idx,things))
- #
- #
- # res = producer()
- # consumer(res)
- #### 生产者 消费者模型
- #### 使用生成器改写上面的程序,实现并发:
- def consumer(name):
- print('我是%s, 我要开始吃包子了.' % name)
- while True:
- baozi=yield
- time.sleep(0.5)
- print('%s 很开心地把 %s 吃掉了.' %(name,baozi))
- def producer():
- c1 = consumer('Tom') # 调用上面的生成器函数
- c1.__next__()
- for i in range(10):
- time.sleep(0.5)
- c1.send('肉包子%s' %i) # 由send
- producer()
- ## 单线程并发
python基础15上_迭代器_生成器的更多相关文章
- Py修行路 python基础 (十一)迭代器 与 生成器
一.什么是迭代? 迭代通俗的讲就是一个遍历重复的过程. 维基百科中 迭代(Iteration) 的一个通用概念是:重复某个过程的行为,这个过程中的每次重复称为一次迭代.具体对应到Python编程中就是 ...
- Python 基础 内置函数 迭代器与生成器
今天就来介绍一下内置函数和迭代器 .生成器相关的知识 一.内置函数:就是Python为我们提供的直接可以使用的函数. 简单介绍几个自己认为比较重要的 1.#1.eval函数:(可以把文件中每行中的数据 ...
- python基础(8)--迭代器、生成器、装饰器
1.迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退.另外,迭代器的一大优 ...
- python基础(八)-迭代器与生成器
一.迭代器 li=[1,2,3] f=li.__iter__() print(f) print(f.__next__()) print(f.__next__()) print(f.__next__() ...
- Python基础(8)迭代器、生成器
一 什么是迭代 1 重复 2 下一次重复是基于上一次的结果 # while True: # cmd=input('>>: ') # print(cmd) # l=['a','b','c', ...
- 2015/9/19 Python基础(15):变量作用域及生成器
变量作用域标识符的作用域是定义为其声明的可应用范围,或者即是我们所说的变量可见性.也就是,我们可以在程序的那个部分去访问一个制定的标识符.全局变量与局部变量定义在函数内的变量有局部作用域,在一个模块中 ...
- day18_文件处理_迭代器_生成器
#!/usr/bin/env python # -*- coding:utf-8 -*- # ********************day18_文件处理_迭代器_生成器 ************** ...
- Python可迭代对象、迭代器和生成器
Python可迭代对象.迭代器和生成器 python 函数 表达式 序列 count utf-8 云栖征文 python可迭代对象 python迭代器 python生成器 摘要: 8.1 可迭代对象( ...
- 十五. Python基础(15)--内置函数-1
十五. Python基础(15)--内置函数-1 1 ● eval(), exec(), compile() 执行字符串数据类型的python代码 检测#import os 'import' in c ...
随机推荐
- [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. 时间复 ...
- 干货 | 揭秘如何增加listing多个类目节点
流量是电商销售的必要因素,可以说,任何成功的电商平台都离不开流量.亚马逊listing优化做得好,不仅能提高产品的曝光率,还能提升转换率,而好的类目可以吸引大的流量.帮你快速爬升. 首先我们来了解一下 ...
- 异常: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,意思 ...
- 安装weblogic
附:wls1036_generic.jar 链接:https://pan.baidu.com/s/1W5g-SHeKL96yrOeDKJJoxw 提取码:vxft 注:以下安装步骤是一个前辈整理的,我 ...
- 判断PDF文件是否相同(通过二进制流判断)
一.Java代码 1.将PDF转为字节流 /* * @step * 1.使用BufferedInputStream和FileInputStream从File指定的文件中读取内容 ...
- requests库/爬取zhihu表情包
先学了requests库的一些基本操作,简单的爬了一下. 用到了requests.get()方法,就是以GET方式请求网页,得到一个Response对象.不加headers的话可能会400error所 ...
- VS2013 密钥– 所有版本
Visual Studio Ultimate 2013 KEY(密钥):BWG7X-J98B3-W34RT-33B3R-JVYW9Visual Studio Premium 2013 KEY(密钥): ...
- Hive中数据的导入与导出
最近在做一个小任务,将一个CDH平台中Hive的部分数据同步到另一个平台中.毕竟我也刚开始工作,在正式开始做之前,首先进行了一段时间的练习,下面的内容就是练习时写的文档中的内容.如果哪里有错误或者疏漏 ...
- asp.net 跨域访问
摘自 https://docs.microsoft.com/en-us/aspnet/web-api/overview/security/enabling-cross-origin-requests- ...
- sql server中如何修改视图中的数据?
sql server中如何修改视图中的数据? 我做个测试,视图的数据有标记字段时,如果是这种方式(0 as FlagState),是无法修改的 --创建视图语句 --- create view V_E ...