一、知识点整理:

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()触发,既将触发写入装饰器中!)

  1. def f(func): #定义装饰器
  2. def f1(*args,**kwargs):
  3. res = func(*args,**kwargs)
  4. next(res) #触发主函数
  5. return res
  6. return f1
  7. @f
  8. def eater(name): #主函数
  9. print("%s start to eat"%name)
  10. while True:
  11. food = yield
  12. print("%s eat %s"%(name,food))
  13. e = eater("zhejiangF4")
  14. e.send("something") #直接传值

执行结果:

  1. zhejiangF4 start to eat
  2. zhejiangF4 eat something

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

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

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

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

  1. import os,time
  2. def init(func):
  3. def wrapper(*args,**kwargs):
  4. res = func(*args,**kwargs)
  5. next(res)
  6. return res
  7. return wrapper
  8.  
  9. @init
  10. def search(target):
  11. '找到文件的绝对路径'
  12. while True:
  13. dir_name=yield
  14. #print('车间search开始生产产品:文件的绝对路径')
  15. time.sleep(1)
  16. g = os.walk(dir_name)
  17. for i in g:
  18. for j in i[-1]:
  19. file_path = "%s\\%s"%(i[0],j)
  20. target.send(file_path)
  21. @init
  22. def opener(target):
  23. '打开文件,获取文件句柄'
  24. while True:
  25. file_path = yield
  26. #print('车间opener开始生产产品:文件句柄')
  27. time.sleep(1)
  28. with open(file_path) as f:
  29. target.send((file_path,f))
  30. @init
  31. def cat(target):
  32. '读取文件内容'
  33. while True:
  34. file_path,f = yield
  35. #print('车间cat开始生产产品:文件的一行内容')
  36. time.sleep(1)
  37. for line in f:
  38. target.send((file_path,line))
  39. @init
  40. def grep(pattern,target):
  41. '过滤一行内容中有无python'
  42. while True:
  43. file_path,line = yield
  44. #print('车间grep开始生产产品:包含python这一行内容的文件路径')
  45. time.sleep(0.2)
  46. if pattern in line:
  47. target.send(file_path)
  48. @init
  49. def printer():
  50. '打印文件路径'
  51. while True:
  52. file_path = yield
  53. #print('车间printer开始生产产品:得到最终的产品')
  54. time.sleep(1)
  55. print(file_path)
  56. g = search(opener(cat(grep('python',printer()))))
  57. g.send('G:\\zhang')

执行结果:

  1. G:\zhang\a3.txt
  2. G:\zhang\a1\a1.txt
  3. G:\zhang\a2\a2.txt

三、列表生成式

  1、由来

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

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

  1. 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)简单代码举例:
  1. egg_list=[]
  2. for i in range(10):
  3. egg_list.append("egg%s"%i)
  4. print(egg_list)
  5.  
  6. l=["egg%s"%i for i in range(10)]
  7. print(l)
  1. 执行结果:
  1. ['egg0', 'egg1', 'egg2', 'egg3', 'egg4', 'egg5', 'egg6', 'egg7', 'egg8', 'egg9']
  2. ['egg0', 'egg1', 'egg2', 'egg3', 'egg4', 'egg5', 'egg6', 'egg7', 'egg8', 'egg9']
  1. 2)稍微有点复杂的,不过也好理解。
  1. #将l 和 s 中每一个元素取出,组成一个新的元组,将所有的结果保存在列表中
  2. l = [1,2,3,4]
  3. s = "hello"
  4. l1 = [(num,s1) for num in l if num >3 for s1 in s]
  5. print(l1)
  6.  
  7. l2 = []
  8. for num1 in l :
  9. if num1 >3:
  10. for s2 in s :
  11. t = (num1 ,s2)
  12. l2.append(t)
  13. print(l2)
  1. 执行结果:
  1. [(4, 'h'), (4, 'e'), (4, 'l'), (4, 'l'), (4, 'o')]
  2. [(4, 'h'), (4, 'e'), (4, 'l'), (4, 'l'), (4, 'o')]
  1. 通过比较,虽然上边两种方式都可以实现功能,但是可以非常明显的看出:运用传统意义上的循环,去编写代码是非常繁琐复杂的。
    而运用 列表生成式,同样的内容,可以通过一个list快速生成实现功能的代码,同时写出的代码非常简洁。

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

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

四、生成器表达式

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

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

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

执行结果:

  1. <generator object <genexpr> at 0x00000000026BB3B8>
  2. {'name': 'tesla', 'price': '', 'count': ''}
  3. {'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. 使用Selenium通过浏览器对网站进行自动化测试和相关问题

    使用Selenium通过浏览器对网站进行自动化测试 自动化测试概念: 一般是指软件测试的自动化,软件测试就是在预设条件下运行系统或应用程序,评估运行结果,预先条件应包括正常条件和异常条件. 广义上来讲 ...

  2. 解决通用串行总线(USB)控制器有感叹号

    (转自:http://blog.sina.com.cn/s/blog_44190ce10101ejth.html)   通用串行总线控制器:由于其配置信息(注册表中的)不完整或已损坏,Windows ...

  3. 获取整个页面HTML的信息以及注意事项

    两种方式: 1.从每个节点获取 var a = '<!DOCTYPE html><html lang="zh-cn">'; var z = "&l ...

  4. NAVagationController

    UINavigationController为导航控制器,在iOS里经常用到. 1.UINavigationController的结构组成 UINavigationController有Navigat ...

  5. 视图框架:Spring MVC 4.0(1)

    目录 一.表单标签库 1.1.简介 1.2.常用属性 1.3.form标签与input标签 1.4.checkbox标签 1.5.radiobutton标签 1.6.password标签 1.7.se ...

  6. 限流之令牌桶算法——RateLimiter官方文档

    原文链接 作者:Dimitris Andreou  译者:魏嘉鹏 校对:方腾飞 RateLimiter 从概念上来讲,速率限制器会在可配置的速率下分配许可证.如果必要的话,每个acquire() 会阻 ...

  7. I.MX6 U-Boot ping网络

    /********************************************************************* * I.MX6 U-Boot ping网络 * 说明: * ...

  8. Ubuntu下安装为知笔记

    之前在Windows下用的是有道云笔记,但是后来开始习惯使用Linux开发,有道云官方并没有提供Ubuntu的版本,所以权衡之下,选择了为知笔记,安装步骤: sudo add-apt-reposito ...

  9. 深入了解ZooKeeper(一)

    在上篇博客ZooKeeper初探之安装和配置中已经对Zookeeper这个“服务协调者”有了初步的认识和了解,一个字“美”,接下来开始深入的交往,开始了解其内心世界! 1. 内容思维导图 2. 分布式 ...

  10. I/O多路复用方案

    1. 本节思维导图 2. 基本的网络编程接口 2.1 基于TCP的通信模型 2.2 基于UDP的通信模型 3. 非阻塞的服务器程序 file.pipe.fifo.socket在默认创建过程中都是阻塞的 ...