# 迭代器和生成器
# 迭代器:
# 双下方法 : 很少直接调用的方法。一般情况下,是通过其他语法触发的
# 可迭代的 —— 可迭代协议 含有__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上_迭代器_生成器的更多相关文章

  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. DB9针和DB25针串口的引脚定义

    <设备监控技术详解>第3章串口设备监控,本章着力介绍串口交换机和串口联网方式.本节为大家介绍标准25针串口的引脚定义. 作者:李瑞民来源:机械工业出版社 3.3 串口线的制作和转换 串口的 ...

  2. Flutter工程无法找到Android真机或Android模拟器

    之前的Flutter的工程链接真机还好好的 结果电脑抽抽了过了个年就连不到真机了 一点run就提示 No connected devices found; please connect a devic ...

  3. prometheus-operator 详细总结(helm一键安装)

    一.介绍prometheus-operator 二.查看配置rbac授权 三.helm安装prometheus-operator 四.配置监控k8s组件 五.granafa添加新数据源 六.监控mys ...

  4. MongDB 批量更新

    最近公司在使用mongodb.  批量更新的语句为: db.table.update(  {'wo': {$in: [ "123", "456"]}}, {$s ...

  5. 爬虫(二)Python网络爬虫相关基础概念、爬取get请求的页面数据

    什么是爬虫 爬虫就是通过编写程序模拟浏览器上网,然后让其去互联网上抓取数据的过程. 哪些语言可以实现爬虫    1.php:可以实现爬虫.php被号称是全世界最优美的语言(当然是其自己号称的,就是王婆 ...

  6. KiB 、十进制单位转换 、二进制单位转换

    KiB是kilo binary byte的缩写,指的是千位二进制字节 KB是kilobyte的缩写,指的是千字节   二进制标准命名   十进制国际单位制SI标准: 1 KB= 1,000 Byte ...

  7. 缓冲区 subprocess 黏包

    一.缓冲区   每个socket被创建以后,都会分配两个缓冲区,输入缓冲区和输出缓冲区,默认大小都为8k,可以通过getsocket()获取,暂时存放传输数据,防止程序在发送数据的时候卡组,提高代码运 ...

  8. 二叉树之AVL树

    高度为 h 的 AVL 树,节点数 N 最多2^h − 1: 最少N(h)=N(h− 1) +N(h− 2) + 1. 最少节点数n 如以斐波那契数列可以用数学归纳法证明: 即: N(0) = 0 ( ...

  9. JavaScript中的this详解

    前言 this用法说难不难,有时候函数调用时,往往会搞不清楚this指向谁?那么,关于this的用法,你知道多少呢? 下面我来给大家整理一下关于this的详细分析,希望对大家有所帮助! this指向的 ...

  10. python(元组,不可修改序列)

    元组也是序列,区别于列表,它不可更改,语法简单只要加逗号隔开即可 1.1,2,3 (1,2,3) 2.42, (42,) 3.3*(40+2) 126 3*(40+2,) (42,42,42) 4.x ...