一、简介

根据指定的规则循环生成数据,当条件不成立时则生成数据结束。数据不是一次性全部生成出来,而是使用一个,再生成一个,好处是可以节约大量的内存。就像设计模式中的懒汉式。适合处理大数据或流数。

生成器是一种特殊的迭代器,使用 yield 关键字而不是 return 来返回值。它可以在迭代过程中动态生成值,而不是一次性生成所有值。

创建生成器的方式: ① 生成器推导式 ② yield 关键字

  • 生成器函数使用关键字yield来返回值。yield = return + next()
  • 调用一个生成器函数,返回的是一个迭代器对象, 而不会执行函数体
  • 生成器函数同时具有迭代器的特性:通过next(gen)方法来获取下一个值。
  • 每次执行next(gen)函数时遇到yield关键字就会return, 并且在下一次执行next(gen)时会从yield关键字的下一行代码开始执行。

二、生成器推导式

元组没有推导式,元组的推导式是

gen = (i for i in range(1, 11) if i % 2 == 0)
# <class 'generator'>
print(type(gen))    
print(next(gen))    # 2
print(next(gen))    # 4

"""
for i=6
for i=8
for i=10
"""
for i in gen:
    print(f"for i={i}")

generator 比 list 占用内存更小。

import sys
my_list =[i for i in range(10000000)]
my_gen =(i for i in range(10000000))
print(type(my_list),type(my_gen))


# getsizeof:查看变量占用的内存大小
print(sys.getsizeof(my_list))       # 89095160
print(sys.getsizeof(my_gen))        # 200

三、yield 关键字

示例1

循环list

def get_list():
    my_list = []
    for i in range(1, 11):
        my_list.append(i)
    return my_list

for i in get_list():
    print(i)

循环生成器

def get_gen():
    for i in range(1, 11):
        yield i

for i in get_gen():
    print(i)

示例2

def generate(n):
    print("初始化代码,只执行一次...")
    i = 1

    while True:
        print(f"循环体={i}")
        if i > n:
            break
        yield i
        i += 1
        print(f"yield i={i}")

print("*" * 10)
gen = generate(3)

print("*" * 10)
print("result=", next(gen))

print("*" * 10)
for x in generate(5):
    print(x)

send(value) 函数可以将参数值传递到生成器内来引用。

  • 调用send(value)方法时第一次必须传None参数,或者在调用send(value)方法前调用next(gen)
  • gen.send(None)==next(gen)
def generate():
    print("初始化代码,只执行一次...")
    i = 1

    while True:
        print(f"循环体={i}")
        if i > 5:
            raise StopIteration
        # send_value 并不影响i的值
        send_value = yield i
        i += 1
        print(f"yield i={i} send_value={send_value}")


gen = generate()
# 初始化代码,只执行一次...
# 循环体=1
# result= 1
print("result=", next(gen))

# yield i=2 send_value=4
# 循环体=2
# result= 2
print("result=", gen.send(4))

# yield i=3 send_value=None
# 循环体=3
# result= 3
print("result=", next(gen))

四、应用场景

def fibonacci():
    """无限斐波那契数列生成器"""
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

fib = fibonacci()
print(next(fib))  # 0
print(next(fib))  # 1
print(next(fib))  # 1
print(next(fib))  # 2
print(next(fib))  # 3

import math

def get_page_data(page_size):
    """
    读取文件中的歌词,一次读取page_size条
    :param page_size: 每页数量
    :return: 每页歌词条数
    """
    #1 读歌词
    with open('./data/bye','r') as file :
        lines = file.readlines()

    #2 总条数
    total_num = len(lines)
    #3 总页数
    total_page = math.ceil(total_num / page_size)
    print(f"total_num={total_num}, page_size={page_size}, total_page={total_page}")
    #4 遍历每页
    for page_no in range(total_page):
        yield lines[page_no * page_size: page_no * page_size + page_size]

data_gen = get_page_data(5)
print(type(data_gen))           # <class 'generator'>
for page_data in data_gen:
    print(page_data)

在这里插入图片描述

在这里插入图片描述

更多推荐