生成器/推导式

1、什么是生成器?

  可以理解为一种数据类型,这种数据类型自动实现了迭代器协议(其他数据类型需要调用自己内置的__iter__方法),所以生成器就是可迭代对象;

2、生成器在python中的表现形式?

  • 生成器函数:常规函数定义,但是使用yield语句而不是使用retum语句返回结果,yield语句一次返回一个结果,在每个结果中间挂机函数的状态,以便下次从他离开的地方执行;
  • 生成器表达式:类似于列表推导,但是生成器返回按需要产生结果的一个对象,而不是一次构建一个列表
#生成器函数(只要函数内部包含有yield关键字,那么函数名()的到的结果就是生成器,并且不会执行函数内部代码)
cp = [1,2,3,4,5]
def test():
    yield 1
    yield 2
    yield 3
date = test()
print(next(date))
print(next(date))
print(next(date))
View Code

 

#三元表达式
name = "lw"
res = "sb" if name == "lw" else "帅哥"
print(res)

egg1 = ["鸡蛋 %s" %i for i in range(10) if i > 5 ]
print(egg1)

#正常列表(在内存中存储)
egg_list = []
for i in range(10):
    egg_list.append("鸡蛋 %s" %i)
print(egg_list)

#列表解析(在内存中存储)
egg = ["鸡蛋 %s" %i for i in range(10)]
print(egg)

#生成器表达式(基于迭代器协议转换成可迭代对象,不占内存)
laomuji = ("鸡蛋 %s" %i for i in range(10))
print(laomuji)   #<generator object <genexpr> at 0x000001A6F46231A8>
print(laomuji.__next__()) #等于next(laomuji)
生成器表达方式

3、生成器取值的几种方式

  • 直接调用生成器内置的__next__方法;生成器内的数据取完,在取会抛出StopIteration
def func():
    print(1)
    yield 5    # 我的函数走到这了
    print(2)
    yield 9    # 我的函数走到这了

g = func()   # 生成一个生成器

print(g.__next__())
print(g.__next__())  # 每次取值会从上一个yield开始
print(g.__next__())  # 生成器内的数据取完,在取会抛出StopIteration
next 取值方法
  • 生成器调用send()方法,send()相当于(next + 传值),传值给yield,第一次调用生成器的时候使用send里边的值必须是None 
def func():
    print(1)
    a = yield 2    # 1.挂起 2.返回值 3.接受值
    print(a)
    print(3)
    b = yield 4
    print(b)
    c = yield 9
g = func()  # 生成一个生成器
print(g.__next__())
print(g.send('123'))
print(g.send('234'))
#第一次调用生成器的时候使用send里边的值必须是None
send 传值方法

 

 4、简述yield与yield from的区别

 

def generator():
    for i in range(5):
        yield i
t = generator()
print(t.__next__())

def generator_1():
    yield 1
    yield 2
    yield 3
    yield 4
    yield 5
t1 = generator_1()
print(t1.__next__())

上面这两种方式是完全等价的,只不过前者更简单一些。
yield

 

def generator1():
    item = range(10)
    for i in item:
        yield i

def generator2():
    yield ‘a‘
    yield ‘b‘
    yield ‘c‘
    yield from generator1() #yield from iterable本质上等于 for item in iterable: yield item的缩写版
    yield from [11,22,33,44]
    yield from (12,23,34)
    yield from range(3)

for i in generator2() :
    print(i)


从上面的代码可以看书,yield from 后面可以跟的式子有“ 生成器  元组 列表等可迭代对象以及range()函数产生的序列”
yield from

 

def test():
    for i in range(10):
        yield i
a = test()
print(a.__next__())
for j in a:
    print(j)

def test():
    yield from range(10)
b = test()
print(b.__next__())
for j in b:
    print(j)

 

5 推导式


# 推导式:
# 1.列表
# 2.集合
# 3.字典
# 4.生成器表达式(只要是小括号的就是生成器表达式)

 

li = []
for i in range(10):
    li.append(i)
print(li)

print([i for i in range(10)])
[结果 语法] #容器

li = []
for i in range(10):
    if i%2 == 1:
        li.append(i)
print(li)

print([i for i in range(10) if i%2 == 0])  # 过滤(筛选)

li = []
for i in range(10):
    for em in range(3):
        li.append(em)
print(li)

print([j for i in range(10) for em in range(3) for j in range(5)])

集合推导式
s = {i for i in range(10)}
print(s)

字典推导式
print({i:i+1 for i in range(10)})

生成器表达式
g = (i for i in range(10))
推导式种类

 

总结:

    #     1.生成器的本质就是一个迭代器
# 2.生成器一定是一个迭代器,迭代器不一定是一个生成器
# 3.生成器是可以让程序员自己定义的一个迭代器
# 4.生成器的好处,节省内存空间
# 5.生成器的特性 一次性的,惰性机制,从上向下
# 6.send相当于 next+传值,第一次触生成器的时候,如果使用send(None)值必须是None,一般我建议你们使用__next__
# 7. python2 iter() next()
# python3 iter() next() __next__() __iter__()
# 8.yield from 将可迭代对象元素逐个返回

 

posted @ 2019-07-13 21:01  self哥  阅读(139)  评论(0编辑  收藏  举报