生成器进阶

def func():
    yield 1
    yield 2
    yield 3

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

-1. 生成器里面的值只能被顺序的取一次,取完就没有了

-2. 生成器里面的值用的时候才取

 

send()

     -send和nex一样 也会走一步到下一个yield停止

     - send和next工作的起止位置是完全相同的
- send可以把一个值作为信号量传递到函数中去
- 在生成器执行伊始,只能先用next
- 只要用send传递参数的时候,必须在生成器中还有一个未被返回的yield
- send()必须传值!但生成器里面可以不接收

def wrapper(func):   #生成器预激装饰器
    def inner(*args,**kwargs):
        g = func(*args,**kwargs)   #g = average_func()
        g.__next__()
        return g
    return inner

@wrapper
def average_func():    #求往天利率平均值
    total = 0
    count = 0
    average = 0
    while True:
        value = yield average  #0  30.0  25.0
        total += value  #30  50
        count += 1      #1   2
        average = total/count  #30  25
g = average_func()
print(g.send(30))
往天利率平均值
 
def func():
    print(1)
    yield 2
    print(3)
    value = yield 4
    print(5)
    yield value

g = func()
print(g.__next__())
print(g.send(88))
print(g.__next__())
#输出 1 2 3 4 5 None
易错点

 

生成器面试题

def add(n,i):
    return n+i

def test():
    for i in range(4):
        yield i

g=test()
for n in [1,10,5]:
    g=(add(n,i) for i in g)
print(list(g))
#[15,16,17,18]

解析:重点是for循环店是一个列表,不管多少次i都是最后一个值

def add(n,i):
    return n+i

def test():
    for i in range(4):
        yield i

g=test()

g=(add(5,i) for i in [0,1,2,3])#5,6,7,8
g=(add(5,i) for i in [5,6,7,8])#10,11,12,13
g=(add(5,i) for i in [0,11,12,13])##[15,16,17,18]
print(list(g))

  

 

列表推导式

new_l = []
for i in [1,3,5]:
    new_l.append(i*i)
print(new_l)

print([i*i for i in [1,3,5]])  #结果必须是一个列表
l = [{'name':'alex','age':80},{'name':'egon','age':40},{'name':'yuan','age':30},{'name':'nezha','age':18}]
print([dic['name'] for dic in l])  #所有的name

print([d['name'] for d in l if d['age'] > 18])  #年龄大于18的所有人的名字
#30以内能被3整除的数
 [0,1,2,3,4,5,6]  = [0,3,6]
print([num for num in range(30) if num%3 == 0])

 

生成器表达式

laomuji = ('egg%d'%i for i in range(10))    #用小括号是生成器表达式
print(laomuji)
names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
         ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
print((name for lst in names for name in lst if name.count('e') >= 2))    #是一个生成器
for i in (name for lst in names for name in lst if name.count('e') >= 2):
    print(i)

三种方法从生成器中取值
#1.a.__next__()
#2.for
for i in laomuji:
print(i)
#3.list强转
print(list(a))

字典推导式

mcase = {'a':10,'b':34}
new_dic = {mcase[k]:k for k in mcase}    #建和值对调
print(new_dic)

mcase = {'a': 10, 'b': 34, 'A': 7, 'Z': 3}
# {a:17,b:34,z:3}    #键变小写,值相加
new_dic = {k.lower():mcase.get(k.lower(),0)+mcase.get(k.upper(),0) for k in mcase}
print(new_dic)

 

集合推导式

l = [-1,1,2,3,4,5]
print([i*i for i in l])     #列表推导式不能去重   
print({i*i for i in l})    #集合推导式能去重

 

# 列表推导式[] - 生成器表达式()
# 尽量让推导式简化你的操作,增强代码的可读性
# 如果推导式过于复杂了,应该转换成普通的python代码
# 所有的列表推导式都可以转换成生成器表达式,并且应该在代码中尽可能多使用生成器表达式而不是列表推导式

#在代码里 多层嵌套的for循环是禁忌 —— 会大幅度增加代码的复杂度


























posted @ 2017-09-05 16:47  选择远方,风雨兼程。  阅读(146)  评论(0编辑  收藏  举报