生成器与推导式

 一,生成器

生成器本质就是迭代器

在python中有三种方式来获取生成器

  1.通过生成器函数

  2.通过各种推到式来实现生成器

  3.通过数据的转换也可以获取生成器

def func():
 
    print(11)
    return 22
 
ret = func()
print(ret)
 
# 运行结果:
11
22

 将函数中的return换成yield就是生成器

#函数
def func():
    print('这是函数func')
    return '函数func'
func()
 
# 生成器
def func1():
    print('这是函数func1')
    yield '函数func' 
func1()
yield
def func():
    print(1)
    # return 5
    yield 5
print(func().__next__())  # 这样生成一个生成器
print(func().__next__())  # 这样生成一个生成器
print(func().__next__())  # 这样生成一个生成器
print(func().__next__())  # 这样生成一个生成器

 

def func():                                       
    print(1)                                      
    yield 2                                       
    print(3)                                      
    yield 4                                       
g=func()                                          
print(g.__next__())                               
print(g.__next__())                               
# 1                                               
# 2                                               
# 3                                               
# 4                                               
print(g.__next__())        #报错    StopIteration   

 

# def func():              
#     print(1)             
#     yield 2              
#     # print(3)           
#     # yield 4            
# print(func().__next__()) 
# print(func().__next__()) 
# print(func().__next__()) 

# 1   只是形成了一个生成器,一直在重复
# 2   
# 1   
# 2   
# 1   
# 2   

 

python2  next() iter()

python3  next() __next__() iter()  __iter__()

 

碰到return就结束函数

碰到yield不结束就挂起

生成器的好处,非常节省内存

send
def func():
    print(1)
    a = yield 2  # 1.挂起 2.返回值 3.接受值
    print(a)   # '123'
    print(3)
    b = yield 4
    print(b)   #'234'

g = func()

print(g.__next__())   #1 2  g.send(None)
print(g.send('123'))  # send = next+传值
# print(g.send('234'))  # send = next+传值

# 1
# 2
# 123
# 3
# 4
def func():
    print(1)
    a = yield 2  # 1.挂起 2.返回值 3.接受值
    print(a)   # '123'
    print(3)
    b = yield 4
    print(b)   #'234'
    c = yield 9

g = func()

print(g.__next__())   #1 2  g.send(None)
print(g.send('123'))  # send = next+传值
print(g.send('234'))  # send = next+传值  #多了一次迭代,应该再加一个yield

 

第一次调用生成器的时候使用send里边的值必须是None

yield from

def func():
    lst = ['卫龙','老冰棍','北冰洋','牛羊配']
    yield from lst
g = func()
for i in g:
    print(i)
def func():
    li = [1,2,3,4]
    # yield li
    yield from li

ret = func()  # 把生成器的地址给了ret
print(ret.__next__())       #1
# # 执行ret这个变量的指向的生成器地址
print(ret)                  #<generator object func at 0x000001B3B3EA97D8>
# # 在全局空间找到一个变量叫做ret的,打印它的值 值就是生成器的地址

 

def func():
    li = [1,2,3,4]
    l2 = [5,6,7,8]
    yield from li
    yield from l2
ret = func()  # 把生成器的地址给了ret
print(ret.__next__())
print(ret.__next__())
print(ret.__next__())
print(ret.__next__())
print(ret.__next__())
def func():
    li = [1,2,3,4]
    l2 = [5,6,7,8]
    # yield from li
    # yield from l2
    for i in li:
        yield i

    for em in l2:
        yield em
#
ret = func()  # 把生成器的地址给了ret
print(ret.__next__())
print(ret.__next__())
print(ret.__next__())
print(ret.__next__())
print(ret.__next__())

 

总结

1.生成器的本质就是一个迭代器

2.生成器一定是一个迭代器,迭代器不一定是一个生成器

3.生成器是可以让程序员自己定义的一个迭代器

4.生成器的好处,节省内存空间

5.生成器的特性 一次性的,惰性机制,从上向下

6.send相当于 next+传值,第一次触生成器的时候,如果使用send(None)

 值必须是None,一般我建议你们使用__next__

7. python2 iter()  next()

python3 iter()  next()  __next__() __iter__()

8.yield from 将可迭代对象元素逐个返回

 二,推导式

1.列表推导式

li = []
for i in range(10):
    li.append(i)
print(li)         #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print([i for i in range(10)])
 #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

 

li = []
for i in range(10):
    if i%2 == 1:
        li.append(i)
print(li)    #[1, 3, 5, 7, 9]
print([i for i in range(10) if i%2 == 0])  # 过滤(筛选)
#[0, 2, 4, 6, 8]
#for 循环的嵌套
li = []
for i in range(10):
    for em in range(3):
        li.append(em)
print(li) 
#[0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2]
print([j for i in range(10) for em in range(3) for j in range(5)])

 

2.集合推导式

s = {i for i in range(10)}
print(s)      #{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

 

3.字典推导式

print({i:i+1 for i in range(10)})   
#{0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}

 

4.没有元组推导式    其实是一个生成器推导式

g = (i for i in range(10))
print(g)    #<generator object <genexpr> at 0x000001D7DD1497D8>

 

 

 总结

1.外部需要容器包一下,  里边第一个位置 结果 剩下位置都是语句

2.推导式 -- 面试  实现小的需求时可以使用推导式,推导式节省代码

3.推导式不要写太长,可读性查.

posted @ 2019-03-16 16:20  Xiao_Xu  阅读(257)  评论(0编辑  收藏  举报