32.生成器

1.取值对比

迭代取值于索引取值对比:
迭代:不依赖于索引取值,通用取值方式。
	 顺序永远都是往下一个取值,无法重复获取。
索引:需要提供有序的容器类型,才能取值,不通用取值方式。
	可以重复取值

2.生成器

2.1定义

生成器 <==> 生成器对象
生成器就是自定义制作迭代器。

2.2定义生成器

关键字 yield 
生成器 ==> 迭代器
但函数体内含有yield关键字 那么在第一调用函数的时候,并不会执行函数代码,而是将函数变成生成器。
def my_ge():
	print('你好')
	yield  

my_ge()  # 不会执行my_ge函数内的内容

2.3获取值

一个yield对应一个__next__。
以yield为分割点分, 一个yield与它之前的代码为迭代器的一个元素。

执行一次.__next__()代码往下运行到yield 就停止,放回后面yield之前的数据。
再次执行一个.__next__()代码接着上次停止的地方继续往后, 在次遇到yield再停止。

如果yield 后面还有语句,而语句后面没有yield,这个语句就不会在执行。
def my_ge():
    print('你好1')
    yield
    print('你好2')
    yield
    print('你好3')
    yield
    print('你好4')
    yield
    print('你好5')  # 不会显示


res = my_ge()
res.__next__()
res.__next__()
res.__next__()
res.__next__()

![在这里插入图片描述](https://img-blog.csdnimg.cn/8226d9c79a5c4db6b8e522db670539a9.png
在这里插入图片描述
在这里插入图片描述

2.4实例

# 模仿range
def my_range(start_num, end_num=None, len_num=1):
    if not end_num:
        end_num = start_num
        start_num = 0

    while start_num < end_num:
        yield start_num
        start_num += len_num


for i in my_range(1, 10, 2):
    print(i)

3yield

3.1对比

yield
1. 可以设置返回值  yield 返回值 (支持多个值并组织成元组。)
	在阻塞在yiele 语句时, 会将yield后面的值放回给迭代器对象。
2. 函数体代码遇到  yield 不会在往后运行 进入阻塞态
3. 第三种传值的方式 yeied 可以将函数变成生成器,还可以接受传值。

return
1.可以有返回值 (支持多个值并组织成元组。)
2.函数体遇到return直接结束

3.2yield传值

yield 有对应的 .send方法进行传值。
格式:
迭代器对象.send(参数1,···)
函数中:
value=yield  
.send()方法 
不带任何参数(None表示)==> 等同于 next 方法
	在阻塞在yiele 语句时, 会将yiele 后面的值返回
带一个参数,先将值通过send传递给tield 在赋值给变量。

3.3不带参数

def my_ge():
    while True:
        yield 1


res = my_ge()
print(res.__next__())  # 1
print(res.__next__())  # 1
def my_ge():
    while True:
        yield 1  # 


res = my_ge()
print(res.send(None))  # 1
print(res.send(None))  # 1

3.4带参数

程序中第一次使用生成器调用 send() 函数时,不能使用带参数的 send() 函数。
def my_ge():
    while True:
        num = yield
        print(num)


res = my_ge()
print(res.send(1))  

"""
# TypeError: can't send non-None value to a just-started generator 报错
无法向刚启动的生成器发送非None值
"""
def my_ge():
    while True:
        num = yield
        print(num)


res = my_ge()

print(res.__next__())
res.send(1)
res.send(2)

4.生成器表达式

生成器表达式内部的代码只有在迭代值的时候才会执行。
迭代器节省空间,只有在我们取值的时候迭代器才会产生值。
d1 = (i for i in range(10))
# print(d1)  # generator 迭代器

for i in d1:
    print(i, end=' ')
# 调用之前是函数 调用之后是生成器
def test():
    for i in range(4):
        yield i


g = test()  # 初始化生成器对象 (0, 1, 2, 3)

for n in [1, 10]:
    g = (i + n for i in g)  # 第一次不执行

res = list(g)
print(res)  # 20 21 22 23

5.作业

import time

# 定义一个相爱的时间
love_time = time.time()

# 我们之间真的想爱
love = True


# 恋爱了多久
def how_long_have_you_been_in_love():
    while love:
        yield time.time() - love_time


# 那么我们我们相爱的那一秒起,我们将注定无限循环,执子之手,与子偕老
for i in how_long_have_you_been_in_love():
    print('\r我们相爱了%d秒, 我对你的喜欢,没有break也没有return, 只有循环!' % i, end='')
    time.sleep(1)
import time
import random

# 定义一个相爱的时间
love_time = time.time()

# 我们之间真的想爱
love = True


# 恋爱了多久
def how_long_have_you_been_in_love():
    while love:
        yield time.time() - love_time


# 搞颜色  30(黑色)、31(红色)、32(绿色)、 33(黄色)、34(蓝色)、35(洋 红)、36(青色)、37(白色)
def color_num():
    num = random.randint(31, 37)
    return num


# 那么我们我们相爱的那一秒起,我们将注定无限循环,执子之手,与子偕老
for i in how_long_have_you_been_in_love():
    num = color_num()
    print(f'\r\033[0;{
      
      num}m我们相爱了%d秒, 我对你的喜欢,没有break也没有return, 只有循环.\033[0m' % i, end='')
    time.sleep(1)
# 变色
import time
import random

# 定义一个相爱的时间
love_time = time.time()

# 我们之间真的想爱
love = True


# 恋爱了多久
def how_long_have_you_been_in_love():
    while love:
        yield time.time() - love_time


# 搞颜色  30(黑色)、31(红色)、32(绿色)、 33(黄色)、34(蓝色)、35(洋 红)、36(青色)、37(白色)
def color_num():
    color = random.randint(31, 37)
    return color


# 那么我们我们相爱的那一秒起,我们将注定无限循环,执子之手,与子偕老
for i in how_long_have_you_been_in_love():
    color = color_num()
    print(f'\r\033[0;{
      
      color}m我们相爱了%d秒, 我对你的喜欢,没有break也没有return, 只有循环.\033[0m' % i, end='')
    time.sleep(0.1)

おすすめ

転載: blog.csdn.net/qq_46137324/article/details/121481092