最新免费视频:www.pythonav.com (冒着被砍死的风险)

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

你第一次看到生成器的样子so beautiful !!!

 

首先  我们学习的迭代器有两种:

1. 调用方法直接返回。   map 和 fileter  (这个我最开始看到也蒙了, 上一篇没有写啊,

于是我问了老师和同学,  暂且先把这个东西就这样记。)

2。 可迭代对象通过执行 iter 方法得到。

 

我们写的能实现迭代器功能的东西就叫做生成器。

 

python 中给我们提供的有生成器:

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

 

2: 生成器表达式: 类似于列表推导(列表推导什么鬼。。。),but but but ,生成器返回按需求产生结果的一个对象,而不是一次构建一个结果列表。    我自己理解的最后这句话意思就是,这个表达式每次只返回一个值, 你要一个我给你一个, 你不要就不要 我也不会硬塞给你。

 

 

生成器Generatol  (顺便回顾下迭代器 iterator 和可迭代的 iterable )

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

  特点: 惰性运算,开发者自定义(开发者自定义什么鬼)

 

生成器函数:

  一个包含了 yield 关键字的函数就是一个生成器函数。yield 可以为我们从函数中返回值。

  yield 和 return 的区别:

return 的执行意味着程序的结束,调用生成器函数不会得到返回的具体的值,而是得到一个可迭代的对象。 y

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

 

来,操练起来。

#先定义函数
import time
def genrator_fun():
a = 3
print('现在定义了变量 a')
yield a
n = a
print(n)
b = 2
print(' 现在定义了变量 b')
yield b

g1 = genrator_fun()
print('g1:',g1)# 这个 print 是看这个 g1 是什么鬼
print('='*20)
print(next(g1))
time.sleep(1)
print(next(g1))

====================
现在定义了变量 a
3
3
现在定义了变量 b
2

 

生成器的好处: 不会一下子在内存中生成太多数据。

 



继续认识生成器:

假如我想让工厂给学生做校服,生产2000000件衣服,我和工厂一说,工厂应该是先答应下来,然后再去生产,我可以一件一件的要,也可以根据学生一批一批的找工厂拿。
而不能是一说要生产2000000件衣服,工厂就先去做生产2000000件衣服,等回来做好了,学生都毕业了。。。

 

def produce():

  '''生产衣服'''

  for i in range(2000000):

    yield('生产了第%s件衣服'%i)

produce_g = produce()

print(produce_g.__next__())#要第一件衣服

print(produce_g.__next__())#要第二件衣服

print(produce_g.__next__())#要第三件衣服

print(produce_g.__next__())#要第四件衣服

 

num = 0 

for i in produce_g:

  print(i)

  num+=1

  if num ==5 :

    break

#到这里我们找工厂拿了8件衣服, 对  是8件,上面三件 下面那个 for i in 那拿了五件,一共八件

我一共让我的生产函数(也就是produce生成器函数)生产2000000件衣服。

剩下的还有2000000-8件衣服,现在情况就是,  我要了你给我, 我不要 你就给我留那,

我什么时候要,你就什么时候立马给,完全服从。

对,就像你和你女朋友的关系。 你懂得。

 

 

 

#生成器监听文件输入的例子
import time
def tail(filename):
f = open(filename)
f.seek(0,2)#从文件末尾算起
while 1 :
line = f.readline()#读取文件中新的文本行
if not line:
time.sleep(0.5)
continue
yield line

tail_g = tail('tmp')
for line in tail_g:
print(line)



#计算移动平均值
def averager():
count =0
total = 0
averager = None
while True:
term = yield averager
total +=term
count+=1
averager = total / count

g_avg = averager()
next(g_avg)
print(g_avg.send(10))
print(g_avg.send(7))
print(g_avg.send(17))

#计算移动的平均值(2)  预激协程的装饰器
def init(func): #在调用被装饰生成器函数的时候首先用 next 激活生成器
def inner(*args,**kwargs):
g = func(*args,**kwargs)
next(g)
return inner


@init
def averager ():
total = 0
count = 0
averager = None
while True:
term = yield averager
total +=term
count +=1
averager = total / count

g_avg = averager()
#next(g_avg) # 在装饰器中执行了 next 方法
print(g_avg.send(666))
print(g_avg.send(777))
print(g_avg.send(888))

'''
导入 time 模块
定义函数(要传参数)
  打开文件 f = open
  f.seek(0,2) 从文件的末尾开始算
  while 1 : while 循环
   if not line:(如果读不到)
    如果读不到就睡一会
      continue 跳过本层
   yield line (返回 line, 并把步骤停在这步)

tail_g = tail()
for line in tail_g:
  print(line)



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



和列表一样,列表推导式也采用方括号[]表示,并且用到了一个简写版的for循环,第一部分是一个生成结果列表元素的表达式,
第二部分是一个输入表达式上的循环。阅读理解列表表达式的推荐做法是先从里面的for循环开始,
向右查看是否有if条件,然后将推导式开始的那个表达式映射到每一个匹配的元素上去。

列表推导式:用[]表示
even_numbers = [x for x in range(10) if x % 2 ==0]
:[0,2,4,6,8]


python还支持另外一种和表列表达式类似的结构,
叫做生成器表达式(generator expression)

它的优点: 1.惰性计算
      2.节省内存





even_numbers = (x for x in range(10) if x%2 ==0)
print(list(even_numbers))
# [0, 2, 4, 6, 8]
在处理大量的数据是,最好考虑生成器表达式而不是列表推导式。

 

另一个列表推导式和生成器表达式的例子是:

 

 
  1. >>> data = ['abc','def','I use python', 'f123']  
  2. >>> sum([len(word) for word in data])  
  3. 25  
  4. >>> sum(len(word) for word in data)  
  5. 25  

enumerate()是一个同时能让你迭代和计数的内置函数,

而for循环自身只能迭代而没办法计数:

 

 
    1. >>> data = [123,"abc",3.14]  
    2. >>> for i in enumerate(data):  
    3. ...     print i  
    4. ...  
    5. (0, 123)  
    6. (1, 'abc')  
    7. (2, 3.14)  






#老男孩由于峰哥的强势加盟很快走上了上市之路,alex思来想去决定下几个鸡蛋来报答峰哥

egg_list=['鸡蛋%s' %i for i in range(10)] #列表解析

#峰哥瞅着alex下的一筐鸡蛋,捂住了鼻子,说了句:哥,你还是给我只母鸡吧,我自己回家下

laomuji=('鸡蛋%s' %i for i in range(10))#生成器表达式
print(laomuji)
print(next(laomuji)) #next本质就是调用__next__
print(laomuji.__next__())
print(next(laomuji))











posted @ 2017-08-05 20:25  uuuuuuu  阅读(188)  评论(0编辑  收藏  举报

最新免费视频:www.pythonav.com (冒着被砍死的风险)