一、知识点整理:

1、可迭代的:对象下有_iter_方法的都是可迭代的对象

迭代器:对象._iter_()得到的结果就是迭代器
 迭代器的特性:
  迭代器._next_() 取下一个值

 优点:
  1.提供了一种统一的迭代对象的方式,不依赖于索引
  2.惰性计算
 缺点:
  1.无法获取迭代器的长度
  2.一次性的,只能往后取值,不能往前退,不能像索引那样去取得某个位置的值

2、生成器:函数内带有yield关键字,那么这个函数执行的结果就是生成器

  生成器的本质就是迭代器

def func():
n=0
  while True:
    yield n
    n+=1
g = func()
next(g)

3、总结yield的功能:
  1、相当于把_iter_和_next_方法封装到函数内部
  2、与return比,return只能返回一次,而yield能返回多次
  3、函数暂停以及继续运行的状态是通过yield保存的

4、yield的表达式形式:  如:food = yield

def eater(name):
  print("%s start to eat"%name)
  while True:
    food = yield
    print("%s eat %s"%(name,food))
e = eater("zhejiangF4")
next(e)
e.send("aaa")  

5、e.send 与 next(e)的区别

#1.如果函数内yield是表达式形式,那么必须先next(e)

#2.二者的共同之处是都可以让函数在上一次暂停的位置继续运行,不一样的地方在于send在触发下一次代码的执行时,会顺便给yield传一个值

二、生成器  协程函数的应用

1、编写一个装饰器,在不变更原代码 协程函数 的基础上,直接就能给主函数传值!(协程函数第一步需要next()触发,既将触发写入装饰器中!)

 def f(func):  #定义装饰器
def f1(*args,**kwargs):
res = func(*args,**kwargs)
next(res) #触发主函数
return res
return f1
@f
def eater(name): #主函数
print("%s start to eat"%name)
while True:
food = yield
print("%s eat %s"%(name,food))
e = eater("zhejiangF4")
e.send("something") #直接传值

执行结果:

 zhejiangF4 start to eat
zhejiangF4 eat something

##在IDE上加上断点,debug运行查看##

2、递归目录,过滤文件中带有“python”内容的文件,然后将这些文件打印。此段代码实现功能,牵扯到面向过程编程的思想!定义的每一个函数都是环环相扣,犹如一个完整的生产线一样!

面向过程的编程思想:流水线式的编程思想,在设计程序时,需要把整个流程设计出来

#优点:
1、体系结构更加清晰
2、简化程序的复杂度
#缺点:
1、可扩展性极其的差,所以说面向过程的应用场景是:不需要经常变化的软件。

 import os,time
def init(func):
def wrapper(*args,**kwargs):
res = func(*args,**kwargs)
next(res)
return res
return wrapper @init
def search(target):
'找到文件的绝对路径'
while True:
dir_name=yield
#print('车间search开始生产产品:文件的绝对路径')
time.sleep(1)
g = os.walk(dir_name)
for i in g:
for j in i[-1]:
file_path = "%s\\%s"%(i[0],j)
target.send(file_path)
@init
def opener(target):
'打开文件,获取文件句柄'
while True:
file_path = yield
#print('车间opener开始生产产品:文件句柄')
time.sleep(1)
with open(file_path) as f:
target.send((file_path,f))
@init
def cat(target):
'读取文件内容'
while True:
file_path,f = yield
#print('车间cat开始生产产品:文件的一行内容')
time.sleep(1)
for line in f:
target.send((file_path,line))
@init
def grep(pattern,target):
'过滤一行内容中有无python'
while True:
file_path,line = yield
#print('车间grep开始生产产品:包含python这一行内容的文件路径')
time.sleep(0.2)
if pattern in line:
target.send(file_path)
@init
def printer():
'打印文件路径'
while True:
file_path = yield
#print('车间printer开始生产产品:得到最终的产品')
time.sleep(1)
print(file_path)
g = search(opener(cat(grep('python',printer()))))
g.send('G:\\zhang')

执行结果:

 G:\zhang\a3.txt
G:\zhang\a1\a1.txt
G:\zhang\a2\a2.txt

三、列表生成式

  1、由来

  在实际编程的情况中,我们常常需要生成一些列表。除了比较低效的用for循环来一个一个往列表中append外,另一个比较好的方法就是:

  python给我们提供了非常强大的创建列表的方式。

2、语法 
  [expression for item1 in iterable1 if condition1
       for item2 in iterable2 if condition2
   for item3 in iterable3 if condition3
   for itemN in iterableN if conditionN]
通俗的来讲,列表生成式由三部分拼接组成:当然每次写之前都应该先给出[],然后在里边添加。
1.expression 指要生成的元素(参数,变量),放在最前面
2.后面跟上for循环
3.for循环之后还可以加上if条件判断,以便进行筛选。
实际使用的过程中,若一个for循环不能完成问题,还可以往下嵌套。
1)简单代码举例:
  egg_list=[]
for i in range(10):
egg_list.append("egg%s"%i)
print(egg_list) l=["egg%s"%i for i in range(10)]
print(l)
执行结果:
 ['egg0', 'egg1', 'egg2', 'egg3', 'egg4', 'egg5', 'egg6', 'egg7', 'egg8', 'egg9']
['egg0', 'egg1', 'egg2', 'egg3', 'egg4', 'egg5', 'egg6', 'egg7', 'egg8', 'egg9']
2)稍微有点复杂的,不过也好理解。
 #将l 和 s 中每一个元素取出,组成一个新的元组,将所有的结果保存在列表中
l = [1,2,3,4]
s = "hello"
l1 = [(num,s1) for num in l if num >3 for s1 in s]
print(l1) l2 = []
for num1 in l :
if num1 >3:
for s2 in s :
t = (num1 ,s2)
l2.append(t)
print(l2)
执行结果:
 [(4, 'h'), (4, 'e'), (4, 'l'), (4, 'l'), (4, 'o')]
[(4, 'h'), (4, 'e'), (4, 'l'), (4, 'l'), (4, 'o')]
通过比较,虽然上边两种方式都可以实现功能,但是可以非常明显的看出:运用传统意义上的循环,去编写代码是非常繁琐复杂的。
而运用 列表生成式,同样的内容,可以通过一个list快速生成实现功能的代码,同时写出的代码非常简洁。

3)再举个例子:读取文件的绝对路径

①代码:
 import os
g = os.walk("G:\\zhang") #拿取文件路径下所有的文件
#print(g) #g是一个生成器
l = []
for i in g: #获取所有文件的绝对路径
#print(i) #路径整体以元组的形式打印出来,元组内部是列表(文件路径,文件名,文件)
for j in i[-1]: #拿取有文件的路径
file_path = "%s\\%s" % (i[0], j)
l.append(file_path)
print(l) g = os.walk("G:\\zhang")
l1 = ["%s\\%s" %(i[0], j) for i in g for j in i[-1]]
print(l1)
##如果不明白怎么来的,可以将代码拷出去,将print释放,打印的结果即可!文件路径可以随意更改!## 
②执行结果:
 ['G:\\zhang\\a3.txt', 'G:\\zhang\\a1\\a1.txt', 'G:\\zhang\\a2\\a2.txt']

四、生成器表达式

1、定义:
生成器表达式,我个人认为还不如叫列表生成器,就是把列表表达式改变了一下,变成了一个生成器。
而且这种改变非常简单,就是把外[]换成了()就创建了一个generator。
通过列表生成式,我们可以直接创建一个列表。但受到内存的限制,列表容量肯定是有限的,同时那么庞大的数据流,一下子拿出来什么机器得卡的受不了。
而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。
在Python中,这种一边循环一边计算的机制,称为生成器:generator。
就昨天所学的生成器的理解来判断:generator生成器保存的是算法,每次通过next()触发取值,并且每次只取一个元素的值,直到计算到最后一个元素。
没有更多的元素时,就会抛出StopIteration的错误。我们可以通过for循环来迭代它,并且不需要关心StopIteration的错误。 这种生成器经常运用于:处理文件,读取数据库中大量的数据 的情况之中。
1、简单代码举例:
 #还是下蛋的例子(……跟鸡过不去了……)
l=['egg%s' %i for i in range(100)]
print(l) g=l=('egg%s' %i for i in range(1000000000000000000000000000000000000))
print(g)
print(next(g))
print(next(g))
for i in g:
print(i)
执行结果:
2、处理文件的代码举例:
 #处理文件,去除文件中每行的空格
#传统处理方式,如果数据很大的话,瞬间将内存挤爆……
f=open('a.txt')
l=[] for line in f:
line=line.strip()
l.append(line)
print(l) f=open('a.txt')
f.seek(0)
l1=[line.strip() for line in f]
print(l1) f=open('a.txt')
f.seek(0)
g=(line.strip() for line in f)
print(g)
print(next(g)) #list(可迭代对象) 可以将迭代器转换成列表
f=open('a.txt')
g=(line.strip() for line in f) l=list(g)
print(l)
执行结果:
['asdfasdfasdfasdfasdf', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'asdfasdfasdfasdf']
['asdfasdfasdfasdfasdf', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'asdfasdfasdfasdf']
<generator object <genexpr> at 0x000000000291B308>
asdfasdfasdfasdfasdf
['asdfasdfasdfasdfasdf', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'asdfasdfasdfasdf']
<generator object <genexpr> at 0x000000000291B3B8>
{'name': 'tesla', 'price': '', 'count': ''}
{'name': 'lenovo', 'price': '', 'count': ''}
3、应用:声明式编程
1)求和函数 sum() 可以计算 可迭代的数据的值
 #1、求和函数 sum() 可以计算 可迭代的数据的值
print(sum([1,2,3,4])) #直接对列表求和
nums_g=(i for i in range(3)) #生成器
print(sum(nums_g))#求和
执行结果:
 10
3
2)计算购物清单总价
 # 计算购物清单总价
# 1、传统方式
money_l=[]
with open('b.txt') as f:
for line in f:
goods=line.split() #将文件中的每行以空格分割,然后以列表的形式保存
res=float(goods[-1])*float(goods[-2]) #求和 个数*单价 此处注意数据类型的转换 str -> float
money_l.append(res) #生成一个总价的列表
print(money_l) #打印列表
print(sum(money_l))#求总价
#
# 2、列表生成器 方法 将上边的代码用声明式编程代替
f=open('b.txt')
g=(float(line.split()[-1])*float(line.split()[-2]) for line in f)
print(sum(g))
#
执行结果:
 [30.0, 1000000.0, 6000.0, 90000.0, 30.0]
1096060.0
1096060.0
3)数据库查询的功能(文件数据,string)得到的内容是[{},{}]形式,列表套字典的形式。
 res=[]
with open('b.txt') as f:
for line in f:
# print(line)
l=line.split() #把每行处理成列表
# print(l)
d={} #先定义一个空字典
d['name']=l[0] #往字典内赋值
d['price']=l[1] #往字典内赋值
d['count']=l[2] #往字典内赋值
res.append(d) #将新创建的字典写到列表中
print(res) #打印结果
#
# 生成器表达式 方式 处理
with open('b.txt') as f:
res=(line.split() for line in f) #得到一个列表生成器 大列表,文件内所有内容都在
#print(res) #查看类型 生成器
dic_g=({'name':i[0],'price':i[1],'count':i[2]} for i in res) #对迭代器进行取值,拿到每个小列表,组成一个新的字典,存放在新的列表中
print(dic_g)#查看类型 生成器
apple_dic=next(dic_g) #取第一值 前提是知道第一个是什么
print(apple_dic['count'])
执行结果:
 [{'name': 'apple', 'price': '', 'count': ''}, {'name': 'tesla', 'price': '', 'count': ''}, {'name': 'mac', 'price': '', 'count': ''}, {'name': 'lenovo', 'price': '', 'count': ''}, {'name': 'chicken', 'price': '', 'count': ''}]
<generator object <genexpr> at 0x00000000028EB360>
3

此处有一个非常有趣的问题,昨天所学,我们知道文件本身就是一个迭代器。

next()取值之后,会将文件关闭。往后就无法再取值,所以会有I/O错误 没法读取 文件关闭的报错。
所以调用文件的话,建议用 f = open("b.txt") 或是next()触发取值的话,缩近放在里边。 4)取出单价>10000 大体不变,只是将每行组成的列表,格式化 转换成字典的时候进行过滤,取出满足条件的内容
 # 取出单价>10000  大体不变,只是将每行组成的列表,格式化 转换成字典的时候进行过滤,取出满足条件的内容
with open('b.txt') as f:
res=(line.split() for line in f)
# print(res)
dic_g=({'name':i[0],'price':i[1],'count':i[2]} for i in res if float(i[1]) > 10000)
print(dic_g)
#print(list(dic_g)) #直接取值
for i in dic_g: #for循环取值
print(i)

执行结果:

 <generator object <genexpr> at 0x00000000026BB3B8>
{'name': 'tesla', 'price': '', 'count': ''}
{'name': 'lenovo', 'price': '', 'count': ''}

Py修行路 python基础 (十二) 协程函数应用 列表生成式 生成器表达式的更多相关文章

  1. python协程函数应用 列表生成式 生成器表达式

    协程函数应用 列表生成式 生成器表达式   一.知识点整理: 1.可迭代的:对象下有_iter_方法的都是可迭代的对象 迭代器:对象._iter_()得到的结果就是迭代器 迭代器的特性: 迭代器._n ...

  2. Py修行路 python基础 (二十五)线程与进程

    操作系统是用户和硬件沟通的桥梁 操作系统,位于底层硬件与应用软件之间的一层 工作方式:向下管理硬件,向上提供接口 操作系统进行切换操作: 把CPU的使用权切换给不同的进程. 1.出现IO操作 2.固定 ...

  3. Py修行路 python基础 (十三)匿名函数 与 内置函数

    一.匿名函数  1.定义: 匿名函数顾名思义就是指:是指一类无需定义标识符(函数名)的函数或子程序. 2.语法格式:lambda 参数:表达式 lambda语句中,开头先写关键字lambda,冒号前是 ...

  4. Py修行路 python基础 (二十)模块 time模块,random模块,hashlib模块,OS及sys模块

    一.前提介绍: 可以开辟作用域的只有类,函数,和模块            for循环 if,else: 不能开辟自己的作用域 避免程序复用和重复调用,将这些写到一个.py文件中,做成一个模块,进行调 ...

  5. Py修行路 python基础 (二十二)异常处理

    异常处理 一.错误和异常 程序中难免出现错误,而错误分为两种:语言异常和逻辑异常 1.语法错误(这种错误,根本过不了python解释器的语法检测,必须在程序执行前就改正) for i in range ...

  6. Py修行路 python基础 (二十四)socket编程

    socket编程 一.客户端/服务端架构 客户端/服务端架构 即C/S架构,包括:1.硬件C/S架构,2.软件C/S架构. 互联网中处处都是C/S架构,学习socket 就是为了完成C/S架构的开发. ...

  7. Py修行路 python基础 (二十三)模块与包

    一.模块 1)定义: 模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀. 2)为何要用模块: 退出python解释器然后重新进入,那之前定义的函数或者变量都将丢失,因 ...

  8. Py修行路 python基础(二)变量 字符 列表

    变量 容器 变量名 标记 数据的作用 字符编码 二进制位 = bit1个二进制位是计算机里的最小表示单元 1个字节是计算机里最小的存储单位 8bits = 1Byte =1字节1024Bytes = ...

  9. Py修行路 python基础 (二十一)logging日志模块 json序列化 正则表达式(re)

    一.日志模块 两种配置方式:1.config函数 2.logger #1.config函数 不能输出到屏幕 #2.logger对象 (获取别人的信息,需要两个数据流:文件流和屏幕流需要将数据从两个数据 ...

随机推荐

  1. Confluence 6 测试电子邮件设置

    一个 Confluence 的管理员可以通过下面的步骤测试电子邮件服务器的配置: 按照上面的步骤中描述得方法设置一个电子邮件服务器. 单击 发送测试邮件(Send Test Email)来检查你设置的 ...

  2. C++(二十一) — 引用概念及本质

     1.引用概念 引用是别名,必须在声明的时候初始化.即:是指一个已定义变量的别名.(一个内存空间,有两个名字都可以操作) 引用:在函数调用时,是变量的别名,不可以单独存在,使用时必须要初始化: 指针: ...

  3. django model_fields_validators 前端页面编辑自定义验证

    # model_field_validators.py import re from django.core.exceptions import ValidationError from django ...

  4. 下载并安装Prism5.0库 Download and Setup Prism Library 5.0 for WPF(英汉对照版)

    Learn what’s included in Prism 5.0 including the documentation, WPF code samples, and libraries. Add ...

  5. tomcat映射物理路径

    <Context path="/woyoubaoweb/upload" docBase="/opt/file/image/woyoubaoweb/upload&qu ...

  6. js不执行的问题

    项目中有两个页面,调用的一个js引用都正确,一个js能用,一个没反应,瞅了半天 没看出什么名堂.最后发现一个页面只有一个 <script type="text/javascript&q ...

  7. python基础之socket编程(二)

    ssh远程执行命令: 思路分析: 客户端给服务端发送命令,服务端返回一个输出结果传给客户端. #coding:utf-8 #买手机 import socket import struct import ...

  8. 条款11:记得在operator=中处理自赋值的情况。

    本来的版本是这样的: Widget & Widget::operator=(Widget rhs) { delete pb;//这里可能直接将rhs的pb删除了 pb = new (*rhs. ...

  9. CSS3 Media Query 响应式媒体查询

    在CSS中,有一个极其实用的功能:@media 响应式布局.具体来说,就是可以根据客户端的介质和屏幕大小,提供不同的样式表或者只展示样式表中的一部分.通过响应式布局,可以达到只使用单一文件提供多平台的 ...

  10. postgresql recovery.conf文件内容说明

    在配置PG主备流复制.HA时,需要用到recovery.conf文件,这里根据自己的了解做个记录: standby_mode = 'on' #说明自己是备库 primary_conninfo = 'u ...