迭代器

字符串、列表、元组、字典、集合都可以被for循环,说明他们都是可迭代的

可迭代协议 : 就是内部实现了__iter__方法

可以被for循环的都是可迭代的,要想可迭代,内部必须有一个__iter__方法。

__iter__方法做了什么事情呢?它返回给我们一个迭代器

迭代器协议:必须拥有__iter__方法和__next__方法。

生成器

我们知道的迭代器有两种:一种是调用方法直接返回的,一种是可迭代对象通过执行iter方法得到的,迭代器有的好处是可以节省内存。

如果在某些情况下,我们也需要节省内存,就只能自己写。我们自己写的这个能实现迭代器功能的东西就叫生成器。

Python中提供的生成器:

1.生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次从它离开的地方继续执行

2.生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表

生成器Generator:

  本质:就是迭代器(所以自带了__iter__方法和__next__方法,不需要我们去实现)

  特点:惰性运算,开发者自定义

生成器函数

一个包含yield关键字的函数就是一个生成器函数。

yield可以为我们从函数中返回值,但是yield又不同于return,return的执行意味着程序的结束,调用生成器函数不会得到返回的具体的值,而是得到一个可迭代的对象。

每一次获取这个可迭代对象的值,就能推动函数的执行,获取新的返回值。直到函数执行结束。

import time
def genrator_fun1():
a = 1
print('现在定义了a变量')
yield a
b = 2
print('现在又定义了b变量')
yield b g1 = genrator_fun1()
print('g1 : ',g1) #打印g1可以发现g1就是一个生成器
print('-'*20) #我是华丽的分割线
print(next(g1))
time.sleep(1) #sleep一秒看清执行过程
print(next(g1))

生成器有什么好处呢?就是不会一下子在内存中生成太多数据

更多应用

import time

def tail(filename):
f = open(filename)
f.seek(0, 2) #从文件末尾算起
while True:
line = f.readline() # 读取文件中新的文本行
if not line:
time.sleep(0.1)
continue
yield line tail_g = tail('tmp')
for line in tail_g:
print(line)

生成器监听文件的例子

send

def generator():
print(123)
content = yield 1
print('=======',content)
print(456)
yield2 g = generator()
ret = g.__next__()
print('***',ret)
ret = g.send('hello') #send的效果和next一样
print('***',ret) #send 获取下一个值的效果和next基本一致
#只是在获取下一个值的时候,给上一yield的位置传递一个数据
#使用send的注意事项
# 第一次使用生成器的时候 是用next获取下一个值
# 最后一个yield不能接受外部的值
def averager():
total = 0.0
count = 0
average = None
while True:
term = yield average
total += term
count += 1
average = total/count g_avg = averager()
next(g_avg)
print(g_avg.send(10))
print(g_avg.send(30))
print(g_avg.send(5))

计算移动平均值

def init(func):  #在调用被装饰生成器函数的时候首先用next激活生成器
def inner(*args,**kwargs):
g = func(*args,**kwargs)
next(g)
return g
return inner @init
def averager():
total = 0.0
count = 0
average = None
while True:
term = yield average
total += term
count += 1
average = total/count g_avg = averager()
# next(g_avg) 在装饰器中执行了next方法
print(g_avg.send(10))
print(g_avg.send(30))
print(g_avg.send(5))

计算移动平均值(2)_预激协程的装饰器

yield from

def gen1():
for c in 'AB':
yield c
for i in range(3):
yield i print(list(gen1())) def gen2():
yield from 'AB'
yield from range(3) print(list(gen2()))

列表推导式和生成器表达式

#列表解析
sum([i for i in range(100000000)])#内存占用大,机器容易卡死 #生成器表达式
sum(i for i in range(100000000))#几乎不占内存

最新文章

  1. Redis百亿级Key存储方案(转)
  2. Style样式
  3. IIS发布问题汇总
  4. javascript中的数组扩展(一)
  5. MYSQL 分组排名
  6. HDU5002 Tree(LCT)
  7. Python系列之文件操作、冒泡算法、装饰器、及递归
  8. MySQL技术内幕汇总
  9. puppeteer(三)常用API
  10. Nginx 模块分类
  11. Linux内核第四节 20135332武西垚
  12. PHPEXCEL xls模板导入,及格式自定义:合并单元格、加粗、居中等操作
  13. Excel日期格式调整
  14. Python相关资料收集
  15. react渲染原理深度解析
  16. .NET Core学习之路
  17. Shell脚本之Crontab的格式
  18. static、final修饰符、内部类
  19. css背景图片拉伸
  20. laravel command命令行

热门文章

  1. Springboot中使用Scheduled做定时任务
  2. Object 中 equals()使用
  3. golang 框架 之 CHI
  4. CSS3_多列布局
  5. vue_源码 原理 剖析
  6. 5. 箭头函数_this 指向_es6 常用语法
  7. 2018-2019-1 20189210 《LInux内核原理与分析》第八周作业
  8. 接线端子VH,CH,XH
  9. POJ 2533 - Longest Ordered Subsequence - [最长递增子序列长度][LIS问题]
  10. Gym 101606L - Lounge Lizards - [计算几何+LIS]