生成器 补充知识点

*********************************昨日补充***********************************

- 生成器中的值会根据顺序一个一个的输出,当到最后一个yield输出后,生成器为空,再使用next取值将会报错,但使用for循环优化结果不会报错

- 生成器里面的值只有在用时才取

def fun():
    yield 1
    yield 2
    yield 3
g=func()
for i in g:
    print(i)          #1,2,3
print(list(g))      #[]

#################
def fun():
    yield 1
    yield 2
    yield 3
g=func()
for i in g:
    print(i)              #1
    print(list(g))      #[2,3]

*********************************今日内容***********************************

- 生成器中send()方法

  - send(n)把生成器中的yield赋值成n,直到遇到下一个yield输出后,停止

    - 注:在生成器开始使用时必须使用next方法,不能使用send

def func():
    print(123)
    value=yield 1              # value=30
print(value) yield 2 print(456) yield 3 g=func() print(g.__next__()) #123,1 print(g.send(30)) # 30,2 print(g.__next__()) #456, 3
def average_func():
    total=0
    count=0
    average=0
    while True:
        value=yield average
        total+=value
        count+=1
        average=total/count
g=average_func()
print(g.__next__())       #激活生成器
print(g.send(10))          #value=10      
print(g.send(20))          #value=20     
print(g.send(50))          #value=50                   

  - 生成器预激活装饰器

def wapper(func):
    def inner(*args,**kwargs):
        g=func(*args,**kwargs)        #g=average_func()

     g.__next__()
return
g
return inner @wapper def average_func(): total=0 count=0 average=0 while True: value=yield average total+=value count+=1 average=total/count g=average_func() print(g.send(10))

  - 小结:

    -send和next工作的起止位置是完全相同的

    -send可以把一个值作为信号量传递到函数中去

    -在生成器执行伊始,只能先用next

    -只要用send传递参数的时候,必须在生成器中还有一个未被返回的yield

  - 在send传入参数时生成器内部没有变量接受

def func():
    print(1)
    yield 2
    print(3)
    value = yield 4
    print(5)
    yield value

g = func()
print(g.__next__())     #1,2
print(g.send(88))        #3,4
print(g.__next__())     #5,None

- 列表推导式与生成器表达式
  - 列表推导式==列表表达式:为了简化代码,结果必须是个列表

#[1,3,5]==>[1,9,25]
new_l = [] for i in [1,3,5]: new_l.append(i*i) print(new_l) #[1,9,25] #列表表达式
print([i*i for i in [1,3,5]) #[1,9,25]

    - 优缺点:优:方便简洁,缺:一次把生成列表,并写进内存中,占用内存大

  - 生成器表达式:把列表推导式的[]换成()得到的就是生成器表达式

  - 生成器表达式:sum(x ** 2 for x in range(4))  

  - 列表表达式:sum([x ** 2 for x in range(4)])

- 生成器表达式  (x ** 2 for x in range(4))  

  - 三种方法从生成器中取值,1.next方法;2.for ;    3.list强转

- 字典推导式

#字典中值与键对调
mcase = {'a':10,'b':34}
print({mcase[i]:i for i in mcase})   # {10: 'a', 34: 'b'}

 

#合并大小写对应的value值,将k统一成小写
mcase = {'a': 10, 'b': 34, 'A': 7, 'Z': 3} new_dic ={k.lower():mcase.get(k.lower(),0)+mcase.get(k.upper(),0) for k in mcase} print(new_dic)

- 集合推导式

squared = {x**2 for x in [1, -1, 2]}
print(squared)     #set([1, 4])

- 生成器小结
  - 把列表解析的[]换成()得到的就是生成器表达式

  - 列表解析与生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存

  - Python不但使用迭代器协议,让for循环变得更加通用。大部分内置函数,也是使用迭代器协议访问对象的。例如, sum函数是Python的内置函数,该函数使用迭代器协议访问对象,而生成器实现了迭代器协议,所以,我们可以直接这样计算一系列值的和:

sum(x ** 2 for x in range(4))

而不用多此一举的先构造一个列表:

sum([x ** 2 for x in range(4)]) 

- 生成器表达式类型于生成器函数,如果没有前面的赋值,是不产生生成器的,即下次调用还是新的开始,它与生成器函数很相似

g=(i for i in range(10))
print(list(g))      #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(list(g))      # []
print(list(i for i in range(10))) #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
l = [i for i in range(0,15)]
print(l)
#[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
m = (i for i in range(0,15))
print(m)
#<generator object <genexpr> at 0x104b6f258>
for i in m:
    print(i,end=',')
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,

   注:不调用不会产生值,不调用不会产生值,不调用不会产生值

 

 

 

  

posted @ 2017-09-05 19:30  JAYWX  阅读(148)  评论(0编辑  收藏  举报