1,复习,迭代器:双下方法很少直接调用,一般都是通过其他语法触发的;迭代器一定可迭代,可迭代的通过调用iter()方法皆可以得到一个迭代器.

迭代器很方便使用,所有的数据只可以取一次,节省内存空间。生成器的本质就是迭代器,调用生成器函数之后,函数并不执行,而是返回一个生成器,

每次调用next方法会返回一个值,知道取完最后一个,在去取会报错

2,作业,写生成器实现:有一个文件,从文件里分段读取内容,在读取出来的内容前加上***返还给调用者,这个作业其实是给网络编程做铺垫

使用readline或者read(1024)实现

3,网络编程的时候,比方说发送一个视频,都是一点一点的发,一点一点的收,但是我们收发的时候,也不是直接就可以发的,都要做一点包装,这儿就会用到生成器。

4,从生成器取值的三个方法:next;for;数据类型的强制转换,这种会占用内存,完全体现不了生成器的初衷(有的面试题会在这儿出题),一般不用

5,使用生成器的核心就是,这个生成数据的过程,可能会被别人反复的使用,所以要封装成函数,但是我们不能把我们要使用的数据都生成了再返回,所以这儿我们用到了生成一条,返回一条,所以我们用到了yield。

6,最后一个yield的后面的代码是拿不到的,使用for可以,next是不可以的

def generator():
print(123)
yield 'a'
print(456)
yield 'b'
print(789) g = generator()
for i in g: # yield 后面的数据,for循环是可以拿到的,但是,使用next是拿不到的,最后一个会报错
print(i) 运行结果:
123
a
456
b
789
def generator():
print(123)
yield 'a'
print(456)
yield 'b'
print(789) g = generator()
print(g.__next__())
print(g.__next__())
print(g.__next__()) 运行结果:
123
Traceback (most recent call last):
a
456
File "/Users/guolixiao/PycharmProjects/lisa's_practise/boys/14.1.py", line 20, in <module>
b
print(g.__next__())
789
StopIteration

7,这里老师有引入了另外一种访问yield的方式,send,必须有一个参数。

def generator():
print(123) num1 = yield 'a' # 第一次 next之后,会执行到yield抛出'a',然后停在这里知道给num1赋值,这儿如果不send的话,num1默认是None
print(num1)
print(456) num2 = yield 'b' # 执行完send之后,"hello"字符串赋值给num1同时执行到第二个yield抛出'b',然后等在这里给num2 赋值
print(num2)
print(789) g = generator()
print('***',g.__next__())
print('***',g.send("hello")) # 只是这样看的话,send的效果next是一样的

8,结论:send获取下一个值的效果和next是一致的,只是在获取下一个值的时候,给上一个yield的位置传递一个数据

9,使用send注意事项:第一次使用的时候,必须使用next获取下一个值,也就是激活一下,最后一个yield不能接收外部的值

10,如果最后一个yield下面如果确实还有代码要执行,但是没有什么值要返回了,怎么办呢,在最后再加一个yield,然后再支撑我做一次next或者send就行了。

def generator():
print(123) num1 = yield 'a' # 第一次 next之后,会执行到yield抛出'a',然后停在这里知道给num1赋值,这儿如果不send的话,num1默认是None
print(num1)
print(456) num2 = yield 'b' # 执行完send之后,"hello"字符串赋值给num1同时执行到第二个yield抛出'b',然后等在这里给num2 赋值
print(num2)
print(789)
yield # 最后会多出来一个none其实就是这个空yield抛出来的 g = generator()
print('***',g.__next__())
print('***',g.send("hello")) # 只是这样看的话,send的效果next是一样的
# print(g.send("world"))
print(g.__next__()) # 最后在加的那个yield支撑我在做一次next或者send

11,相对与yield和next,这个send其实用的相对少,next和for,和使用列表取值是必会的,send也要求知道,作用范围和next是一样的,如果不需要往生成器传值,next就可以了,只有我要拿的值,依赖于我往里传的值,才用send。

12,一个例子:获取移动平均值,send不可以在第一个用,第一个必须是next,一个循环里面只可以有一个yield,遮掩才能保证每次send 一次会产生一个新的值

def ava_sum():

    num = 0
sum = 0
count = 0
ava_num = 0
while True:
num = yield ava_num
count += 1
sum += num
ava_num = sum/count g = ava_sum()
g.__next__()
ret = g.send(5)
print(ret) ret = g.send(10)
print(ret) ret = g.send(3)
print(ret) ret = g.send(2)
print(ret) 运行结果:
5.0
7.5
6.0
5.0

13,由于上面的移动平均值生成器函数,每次一开始要用一次next激活一下,这有点不友好,我希望一拿到这个函数,就可以直接send了,怎么办?解释器

# 预激生成器功能的装饰器
def init(f):
def inner(*args,**kwargs):
g = f(*args,**kwargs)
g.__next__() # 只需要加一句这个就可以了
return g
return inner @init
def ava_sum(): num = 0
sum = 0
count = 0
ava_num = 0
while True:
num = yield ava_num
count += 1
sum += num
ava_num = sum/count g = ava_sum()
ret = g.send(5)
print(ret) ret = g.send(10)
print(ret) ret = g.send(3)
print(ret) ret = g.send(2)
print(ret) 运行结果:
5.0
7.5
6.0
5.0

14,上面多了一个装饰器,下面少些了一个next,因为所有跟send相关的都要激活才可以,加上同一个装饰器就可以少些很多部,对于用户来说就更直观了。用户使用时更方便了

15,python3里面新加入一个知识点,yield from用在生成器函数里面,从容器类型里面一个一个取值。

def generator():
a = ''
yield from a
b = 'abcde'
yield from b # 同一个生成器,每个值只可以取一次
# yield from会把所有制打散来取
g = generator()
print(g.__next__())
print('================')
for i in g:
print(i) 运行结果:
1
================
2
3
4
5
a
b
c
d
e
def generator():
a = ''
yield a
b = 'abcde'
yield b # 同一个生成器,每个值只可以取一次
# yield from会把所有值打散来取
g = generator()
print(g.__next__())
print('================')
for i in g:
print(i) 运行结果:
12345
================
abcde

16, 我们还可以这样来写,但是不推荐

def generator():
a = ''
for i in a:
yield i
b = 'abcde'
for i in b:
yield i # 同一个生成器,每个值只可以取一次
# yield from会把所有制打散来取
g = generator()
print(g.__next__())
print('================')
for i in g:
print(i) 运行结果:
1
================
2
3
4
5
a
b
c
d
e

17,列表推导式:其实就是一种简单的语法,获取一个列表

li = ["lisa%s"%i for i in range(10)]
print(li) #结果就是一个列表
运行结果:
['lisa0', 'lisa1', 'lisa2', 'lisa3', 'lisa4', 'lisa5', 'lisa6', 'lisa7', 'lisa8', 'lisa9']

18,上面的语法和下面的for循环,效果是一样的

li = []
for i in range(10):
li.append('lisa%s'%i) print(li)
运行结果:
'lisa0', 'lisa1', 'lisa2', 'lisa3', 'lisa4', 'lisa5', 'lisa6', 'lisa7', 'lisa8', 'lisa9']

19,其他的列表推导式:

li = [i*2 for i in range(10)]
print(li)
li = [i*i for i in range(10)]
print(li)
li = [i for i in range(10)]
print(li) 运行结果:
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

20,生成器表达式:只要把列表推导式的中括号换成圆括号就变成了生成器表达式,不同点一,括号不一样,第二点不同,返回值不一样,一个返回列表,一个返回一个生成器,生成器表达式运行快,而且几乎不占用内存,这是他比列表表达式好的地方,用户虽然不关心这些,但是我们要关心的,表达式比较简单,并不能满足所有需求,类似三元运算符号,都是比较简单的问题,他能实现的功能,生成式函数都可以实现,一些面试题比较喜欢考这儿。

g = (i for i in range(5)) # 运行到这里只是返回了一个生成器,里面的代码并没有执行
print(g)
for i in g:
print(i) # 走到print,生成器里面的代码才会运行 运行结果:
<generator object <genexpr> at 0x10a1135e8>
0
1
2
3
4

21,老师把生成器比喻成了老母鸡,取值i比喻成鸡蛋,很贴切,但是实际代码,不写中文

22,带条件的生成器表达式:

# [每一个元素或者是和元素相关的操作 for 元素 in 可迭代数据]
# [每一个元素或者是和元素相关的操作 for 元素 in 可迭代数据 if 元素相关的条件] # 30以内能被3整除的数
g = (i for i in range(30) if i%3 ==0)
for i in g:
print(i) 运行结果:
0
3
6
9
12
15
18
21
24
27

23,找出嵌套列表中,名字含有两个字母e的名字,其实多层嵌套,并不是很常用,既要简洁,又要可读,嵌套列表其实用的并不多,要写的大家都可以看得懂,列表推导式里面的,打断点都不好使,直接就出来了,在复杂一点的话,还不如用for循环。

# 嵌套列表,前面女,后面男
li =[['Lisa','Mary','Jeniffer','Lucy'],['Tom','Steven','Jack','Wesley']]
g = (name for list_line in li for name in list_line if name.count('e')==2)
for i in g:
print(i) # for的顺序,先for外面的大列表,再for里面的小列表

24,字典推导式和集合推导式,这两个了解就行了,但是前面的列表推导式是要求会的

# 字典表达式,需要用大括号括起来

# 例一:要求将上面的字典key 和value对调,生成新的字典
my_dict = {'a':20,'b':10,'c':30}
my_new_dict = {my_dict[k]:k for k in my_dict}
print(my_new_dict) # 例二:合并大小写对应的value值,将k统一成小写
my_dict = {'a':20,'b':10,'c':30,'A':40,'C':60}
my_new_dict = {k.lower():my_dict.get(k.lower(),0)+my_dict.get(k.upper(),0) for k in my_dict}
# get函数,可以不存在是默认抛出0 dict1 = {'a':20,'b':10}
print(dict1.get('c',0)) # 没哟这个key 的时候回抛出0 运行结果
{20: 'a', 10: 'b', 30: 'c'}
{'a': 60, 'b': 10, 'c': 90}
0

25,集合推导式,最大的作用就是去重

my_set = {x*x for x in [1,-1,2,-3,3]}
print(my_set) 运行结果:
{1, 4, 9}

26,各种推导式,两个操作,遍历操作,筛选操作,支持各种推到式,让代码更简洁,但不要写的太复杂了

27,可迭代对象,迭代器,生成器:惰性运算,生成器,一次返回一个结果,生成器我们自己写的,很明显,迭代器是Python自己写的,不明显,但是其实也是惰性的,这对于处理大数据来说是非常有用的。另外提高代码的可读性,同一个迭代器,取值只可以取一次,不找他要值,不干活。

day14: 生成器进阶的更多相关文章

  1. day14.生成器进阶,推导式

    生成器中取值的三种方法 方法1:next() 方法2:for 循环 方法3:数据类型的强制转换 def func(): for i in range(20): yield '赛车*{}'.format ...

  2. python基础(9)-迭代器&生成器函数&生成器进阶&推导式

    迭代器 可迭代协议和迭代器协议 可迭代协议 只要含有__iter__方法的对象都是可迭代的 迭代器协议 内部含有__next__和__iter__方法的就是迭代器 关系 1.可以被for循环的都是可迭 ...

  3. 十三. Python基础(13)--生成器进阶

    十三. Python基础(13)--生成器进阶 1 ● send()方法 generator.send(value) Resumes the execution, and "sends&qu ...

  4. Python的生成器进阶玩法

    Python的生成器进阶玩法 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.yield的表达式形式 #!/usr/bin/env python #_*_coding:utf-8 ...

  5. DAY14(PYTHONS)生成器进阶

    def average(): sum = 0 count = 0 avg = 0 while True: #循环 num = yield avg #遇到yield就停止,防止一开始除数为0导致崩溃 s ...

  6. day14 生成器的进阶

    一.生成器的两种形式  1.生成器函数的应用 # def cloth(): # for i in range(100): # yield '衣服%s'%i # # g = cloth() # for ...

  7. python基础一 day14 生成器函数进阶

    def generator(): print(123) content = yield 1 print('=======',content) print(456) arg = yield 2 '''' ...

  8. python基础一 day14 生成器函数进阶(1)

  9. day14.生成器迭代器作业

    1.写生成器,从文件中读取内容,再每一行读取的内容前加上 ‘***’之后返回给用户 def func(filename): word = input('输入你想找的内容:') with open(fi ...

随机推荐

  1. cocos2d-x与UIKit混合编程实现半透明效果

    关键词 cocos2d-x, UIKit, transparent 问题 cocos2d-x使用一个专门的OpenGL View进行渲染, 它的渲染和UIKit是分开进行的, 因此我们使用时一般是把c ...

  2. 深入浅出理解c++虚函数

    深入浅出理解c++虚函数   记得几个月前看过C++虚函数的问题,当时其实就看懂了,最近笔试中遇到了虚函数竟然不太确定,所以还是理解的不深刻,所以想通过这篇文章来巩固下. 装逼一刻: 最近,本人思想发 ...

  3. 【Java多线程】JDK1.5并发包API杂谈

    并发与并行 并发 一个或多个处理器执行更多的任务(通过划分时间片来执行更多的任务),从逻辑上实现同时运行: 如,N个并发请求在一个两核CPU上: 并行 N个处理器分别同时执行N个任务,从物理上实现同时 ...

  4. SILK 预测模块分析

    SILK是一种新结构的基于噪声整形量化算法的编解码框架.不同于类CELP的AMR,EVRC,G729,Speex等标准. 类CELP的结构都是以码本激励为量化框架的编码器.但是这里并不讨论NSQ结构和 ...

  5. (原创)Python文件与文件系统系列(1)—— file 对象

    本系列将从四个部分简单介绍Python对文件系统的操作与支持: 1. Python内置的 file 对象 2. Python的os模块对文件.文件系统操作的支持 3. Python的os.path模块 ...

  6. GDC2017 把“现实的天空”在游戏内再现【Forza Horizon 3】的天空表现

    原文链接 http://game.watch.impress.co.jp/docs/news/1047800.html 完全表现出现实世界中各种偶然而不可预料的风景!     [Forza Horiz ...

  7. Python爬虫学习——布隆过滤器

    布隆过滤器的实现方法1:自己实现 参考 http://www.cnblogs.com/naive/p/5815433.html bllomFilter两个参数分别代表,布隆过滤器的大小和hash函数的 ...

  8. Ubuntu下搜狗输入法只显示黑框,不显示输入的汉字选项

    1. cd ~/.config 2.删除三个文件夹: SogouPY, SogouPY.users, sogou-qimpanel 然后重启输入法

  9. Scala学习笔记(五):内建控制循环

    前言 Scala中内建控制循环包括if.while.for.try.match和函数调用. if和while与java类似,不做介绍. for 基础用法 def main(args: Array[St ...

  10. duilib进阶教程 -- TreeView控件的不足 (7)

    上一个教程中,虽然播放列表的框架和迅雷一样了,但是字体大小.文字居中还没有解决.如果是刚学duilib,搞定这个可不容易,因为在有了入门教程的指导后,很容易就想到去看[属性列表.XML],但是当你试了 ...