python函数(5):迭代器和生成器
迭代器和生成器是函数中的一大重点,务必掌握,何为迭代?何为迭代器?
预习:
1、处理文件,用户指定要查找的文件和内容,将文件中包含要查找内容的每一行都输出到屏幕(使用生成器)
2、批量处理文件,用户指定要查找的目录和内容,将本层目录下所有文件中包含要查找内容的每一行都输出到屏幕
本篇导航:
一、可迭代的
for i in 50:
print(i)
#运行结果:
# Traceback (most recent call last):
# File "G:/python/python代码/八月/day2 迭代器生成器/3迭代器.py", line 8, in <module>
# for i in 50:
# TypeError: 'int' object is not iterable
报错:
TypeError: 'int' object is not iterable
类型报错:'int'对象是不可迭代的 何为迭代?
iterable:可迭代的;迭代的;
可迭代的:从上面代码可以简单分析出能被for循环取值的就是可迭代,那么我们就可以初步总结出可迭代的类型:str、list、tuple、set、dict
可迭代的 ——对应的标志 拥有__iter__方法
print('__iter__' in dir([1,2,3])) #判断一个变量是不是一个可迭代的
可迭代协议
可以被迭代要满足的要求就叫做可迭代协议。可迭代协议的定义非常简单,就是内部实现了__iter__方法。
二、迭代器
__iter__方法作用:
l = [1,2,3,4,5]
print(l.__iter__())
l_iterator = iter(l) #建议用iter(l)
print(set(dir(l_iterator))-set(dir(l)))
#结果:
#<list_iterator object at 0x000001FDD1B79048>
#{'__length_hint__', '__next__', '__setstate__'}
迭代器
iterator:迭代器;迭代程序
迭代器协议:必须拥有__iter__方法和__next__方法
通过iter(x)得到的结果就是一个迭代器,
x是一个可迭代的对象
在for循环中,就是在内部调用了__next__方法才能取到一个一个的值。
__next__的精髓:
l = [1,2,3,4,5]
l_iterator = iter(l)
print(l_iterator.__next__())
print(l_iterator.__next__())
print(l_iterator.__next__())
print(l_iterator.__next__())
print(l_iterator.__next__())
next(l_iterator) #==l_iterator.__next__()
while True:
try:
print(next(l_iterator))
except StopIteration:
break
__next__方法的使用精髓
如果我们一直取next取到迭代器里已经没有元素了,就会报错(抛出一个异常StopIteration),告诉我们,列表中已经没有有效的元素了。这个时候,我们就要使用异常处理机制来把这个异常处理掉。try_except异常处理机制只做了解,不是本章重点,会面会详细讲解。
判断是否可迭代和迭代器的简洁方法:
from collections import Iterable
from collections import Iterator
s = 'abc'
print(isinstance(s,Iterable))
print(isinstance(s,Iterator))
print(isinstance(iter(s),Iterator))
判断可迭代和迭代器
不管是一个迭代器还是一个可迭代对象,都可以使用for循环遍历
迭代器出现的原因 帮你节省内存
三、生成器
迭代器大部分都是在python的内部去使用的,我们直接拿来用就行了
我们自己写的能实现迭代器功能的东西就叫生成器。
1.生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重它离开的地方继续执行
2.生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表
生成器Generator:
本质:迭代器(所以自带了__iter__方法和__next__方法,不需要我们去实现)
特点:惰性运算,开发者自定义
#生成器函数
def func():
print('aaaa')
a = 1
yield a #返回第一个值
print('bbbb')
yield 12 #返回第二个值 ret = func() #拿到一个生成器
# print(ret) #<generator object func at 0x0000028AE2DA2EB8>
print(next(ret)) #取第一个值
print(next(ret)) #取第二个值
print(next(ret)) #取第三个值 会报错 因为没有第三个值 def make_cloth():
for i in range(2000000):
yield "第%s件衣服"%i szq = make_cloth()
print(next(szq))
print(next(szq)) print(next(szq))
for i in range(50):
print(next(szq))
生成器函数
生成器的好处:不会一下子在内存中生成太多数据
其它应用:
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)
生成器监听文件输入的例子
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))
计算移动平均值升级_生成器激活装饰器
def func():
# for i in 'AB':
# yield i
yield from 'AB' #等同于上面两行
yield from [1,2,3]
g = func()
print(next(g))
print(next(g))
print(next(g))
print(next(g))
yield from
四、列表推导式和生成器表达式
for i in range(100):
print(i*i) l =[i*i for i in range(100)] #列表推导式
print(l) l = [{'name':'v','age':28},{'name':'v'}]
name_list = [dic['name'] for dic in l] #列表推导式
print(name_list) l = [{'name':'v1','age':28},{'name':'v2'}]
name_list_generator = (dic['name'] for dic in l) #生成器表达式
print(name_list_generator)
print(next(name_list_generator))
print(next(name_list_generator)) egg_list=['鸡蛋%s' %i for i in range(10)] #列表推导式
print(egg_list) laomuji = ('鸡蛋%s' %i for i in range(1,11)) #生成器表达式
print(laomuji)
print(next(laomuji))
print(next(laomuji))
列表推导式和生成器表达式
使用生成器的优点:
1、延迟计算,一次返回一个结果。也就是说,它不会一次生成所有的结果,这对于大数据量处理,将会非常有用。
2、提高代码可读性
#列表解析
sum([i for i in range(100000000)])#内存占用大,机器容易卡死 #生成器表达式
sum(i for i in range(100000000))#几乎不占内存
总结:
1、把列表解析的[]换成()得到的就是生成器表达式
2、列表解析与生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存
3、Python不但使用迭代器协议,让for循环变得更加通用。大部分内置函数,也是使用迭代器协议访问对象的。例如, sum函数是Python的内置函数,该函数使用迭代器协议访问对象,而生成器实现了迭代器协议,所以,我们可以直接这样计算一系列值的和
print(sum([1,2,3]))
print(sum(range(1,4)))
print(sum(x ** 2 for x in range(4)))
print(sum([x ** 2 for x in range(4)]))
思维导图:
预习答案:
def grep_file(filename,grep_content):
f = open(filename)
for line in f:
if grep_content in line:
yield line g = grep_file('tmp_file','python')
for line in g:
print(line,end='')
普通青年版(1题)
def init(func):
def inner(*args,**kwargs):
g = func(*args,**kwargs)
next(g)
return g
return inner @init #grep_file = init(grep_file)
def grep_file(grep_content,printer_g):
while True:
filename = yield
f = open(filename)
for line in f:
if grep_content in line:
printer_g.send(line) @init ##printer = init(printer) 激活print_g
def printer():
while True:
line = yield
if line:print(line,end='') grep_g = grep_file('python', printer())
grep_g.send('tmp_file')
妖孽青年版(1题)
import os
def getpath(filepath):
g = os.walk(filepath)
for par_dir, _, files in g:
for file in files:
yield par_dir + "\\" + file # 2打开文件对象发给3
def getfile(filepaths):
for filepath in filepaths:
with open(filepath, encoding="utf-8") as file:
yield file # 3读取每一行发给4
def getline(files):
for file in files:
for line in file:
yield line # 4判断pattern发给5
def grep(lines, pattern):
for line in lines:
if pattern in line:
yield line # 5打印文件名
def printname(strings):
for string in strings:
print(string) filepath = r"F:\Code\Python\LearnPython\Day14 generator"
pattern = "jean" printname(grep(getline(getfile(getpath(filepath))), pattern))
妖孽升级版(2题)
python函数(5):迭代器和生成器的更多相关文章
- Python 函数之迭代器和生成器
1.迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退,迭代器仅仅在迭代到某个元素时才计算该元素,而在这之前或之后,元素可 ...
- python is、==区别;with;gil;python中tuple和list的区别;Python 中的迭代器、生成器、装饰器
1. is 比较的是两个实例对象是不是完全相同,它们是不是同一个对象,占用的内存地址是否相同 == 比较的是两个对象的内容是否相等 2. with语句时用于对try except finally 的优 ...
- python设计模式之迭代器与生成器详解(五)
前言 迭代器是设计模式中的一种行为模式,它提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示.python提倡使用生成器,生成器也是迭代器的一种. 系列文章 python设计模 ...
- Python 闭包、迭代器、生成器、装饰器
Python 闭包.迭代器.生成器.装饰器 一.闭包 闭包:闭包就是内层函数对外层函数局部变量的引用. def func(): a = "哈哈" def func2(): prin ...
- Python开发——函数【迭代器、生成器、三元表达式、列表解析】
递归和迭代 小明问路篇解释说明 递归:小明——>小红——>小于——>小东:小东——>小于——>小红——>小明 小明向小红问路,因小红不知道,所以向小于问路,因小于不 ...
- 【python基础】迭代器和生成器函数
1.迭代器协议: 1.迭代器协议是指:对象必须提供一个 __next__() 方法,执行该方法要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代(只能往后走不能往前退) ...
- Python函数系列-迭代器,生成器
一 迭代器 一 迭代的概念 #迭代器即迭代的工具,那什么是迭代呢?#迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的结果都是下一次迭代的初始值 while True: #只是单纯地重复,因而不 ...
- Python学习笔记:输入输出,注释,运算符,变量,数字类型,序列,条件和循环控制,函数,迭代器与生成器,异常处理
输入输出 输入函数input()和raw_input() 在Python3.x中只有input()作为输入函数,会将输入内容自动转换str类型: 在Python2.x中有input()和raw_inp ...
- Python中的迭代器和生成器
本文以实例详解了python的迭代器与生成器,具体如下所示: 1. 迭代器概述: 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后 ...
- Python学习--07迭代器、生成器
迭代 如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们称为迭代(Iteration). Python里使用for...in来迭代. 常用可迭代对象有 ...
随机推荐
- redisLock redis分布式锁
redis-lock redis setnx cmmand java object condition queue 条件队列 retrycount 带有重试次数限制 object wait time ...
- [转] SOLID五大设计原则
我们知道,面向对象对于设计出高扩展性.高复用性.高可维护性的软件起到很大的作用.我们常说的SOLID五大设计原则指的就是: S = 单一职责原则 Single Responsibility ...
- ORA-12638: 身份证明检索失败 解决方法
用PL/SQL或Navicat连接本地或远程Oracle数据库的时候报错:ORA-12638: 身份证明检索失败 解决方法: 开始 -> 所有程序 -> Oracle - Oracle_h ...
- Java IO学习笔记五
管道流 管道流的主要作用是可以进行两个线程间的通讯,分为管道输出流(PipedOutputStream).管道输入流(PipedInputStream),如果想要进行管道输出,则必须要把输出流连在输入 ...
- udl文件测试数据库连接
直接建一个udl后缀的文件(新建txt文件,改后缀) 然后会默认有个小电脑标志,双击打开就可以看到,可以用来配置数据库连接信息,可以测试连接,如果连接通过,可以再用记事本打开这个udl文件,里面就有生 ...
- 关于cookie与session的理解
服务器端并不能捕获客户端的浏览器关闭事件,因此你关闭浏览器以后,服务器端那个Session还是存在的,要超时以后才被回收,启动一个新的浏览器会启动一个新的session,所以他不认你了session永 ...
- css里面position:relative与position:absolute的区别
position:absolute这个是绝对定位:是相对于浏览器的定位.比如:position:absolute:left:20px;top:80px; 这个容器始终位于距离浏览器左20px,距离浏览 ...
- 第14章 Linux开机详细流程
本文目录: 14.1 按下电源和bios阶段 14.2 MBR和各种bootloader阶段 14.2.1 boot loader 14.2.2 分区表 14.2.3 采用VBR/EBR方式引导操作系 ...
- 5.Smart使用内置函数或者自定义函数
1.使用内置函数 例如使用date函数 {"Y-m-d"|date:$time}格式{第一个参数|方法:第二个参数:第三个参数}即可转换成 2016-07-19 2.使用resi ...
- (转载)oracle的v$sqlarea表
原文摘自:http: [V$SQLAREA] 本视图持续跟踪所有shared pool中的共享cursor,在shared pool中的每一条SQL语句都对应一列.本视图在分析SQL语句资源使用方面 ...