生成器是Python中一种特殊的迭代器,它允许你按需生成值,而不是一次性生成所有值。这在处理大量数据或无限序列时非常有用。

基本概念

什么是生成器?

生成器是一个返回生成器迭代器的函数,它使用yield语句而不是return来返回值。当生成器函数被调用时,它返回一个生成器对象,但不会立即执行函数体。

生成器 vs 普通函数

普通函数:使用return返回值,执行后立即退出
生成器函数:使用yield返回值,每次产生一个值后暂停,下次从暂停处继续

创建生成器

方法1:使用生成器函数

def simple_generator():
    yield 1
    yield 2
    yield 3

# 使用生成器
gen = simple_generator()
print(next(gen))  # 输出: 1
print(next(gen))  # 输出: 2
print(next(gen))  # 输出: 3
# print(next(gen))  # 抛出 StopIteration 异常

方法2:使用生成器表达式

将列表推导式的中括号修改为圆括号。

# 类似于列表推导式,但使用圆括号
squares = (x*x for x in range(5))

print(next(squares))  # 输出: 0
print(next(squares))  # 输出: 1
print(next(squares))  # 输出: 4

# 或者使用循环
for value in squares:
    print(value)  # 输出: 9, 16

生成器的特点

1. 惰性求值

def count_up_to(max):
    count = 1
    while count <= max:
        yield count
        count += 1

counter = count_up_to(5)
for num in counter:
    print(num)  # 输出: 1, 2, 3, 4, 5

2. 内存效率高

# 普通函数 - 一次性生成所有值
def get_all_squares(n):
    result = []
    for i in range(n):
        result.append(i*i)
    return result

# 生成器 - 按需生成值
def generate_squares(n):
    for i in range(n):
        yield i*i

# 对于大n,生成器更节省内存

3. 无限序列

def infinite_sequence():
    num = 0
    while True:
        yield num
        num += 1

inf_gen = infinite_sequence()
for i in range(5):
    print(next(inf_gen))  # 输出: 0, 1, 2, 3, 4

高级用法

1. 使用send()方法传递值

def generator_with_send():
    value = yield "Ready"
    yield f"Received: {value}"

gen = generator_with_send()
print(next(gen))        # 输出: Ready
print(gen.send("Hello")) # 输出: Received: Hello

2. 使用throw()方法抛出异常

def resilient_generator():
    try:
        yield "Start"
        yield "Continue"
    except ValueError as e:
        yield f"Error handled: {e}"
        yield "Recovered"

gen = resilient_generator()
print(next(gen))        # 输出: Start
print(gen.throw(ValueError("Test error")))  # 输出: Error handled: Test error
print(next(gen))        # 输出: Recovered

3. 使用close()方法关闭生成器

def simple_gen():
    try:
        yield 1
        yield 2
        yield 3
    except GeneratorExit:
        print("Generator closed")

gen = simple_gen()
print(next(gen))  # 输出: 1
gen.close()       # 输出: Generator closed

实际应用示例

1. 读取大文件

def read_large_file(file_path):
    with open(file_path, 'r') as file:
        for line in file:
            yield line.strip()

# 逐行处理大文件,不一次性加载到内存
for line in read_large_file("large_file.txt"):
    process_line(line)  # 假设process_line是处理行的函数

2. 生成斐波那契数列

def fibonacci(limit):
    a, b = 0, 1
    count = 0
    while count < limit:
        yield a
        a, b = b, a + b
        count += 1

for num in fibonacci(10):
    print(num)  # 输出前10个斐波那契数

3. 管道处理数据

def read_data():
    for i in range(10):
        yield i

def filter_even(numbers):
    for num in numbers:
        if num % 2 == 0:
            yield num

def square(numbers):
    for num in numbers:
        yield num * num

# 创建处理管道
pipeline = square(filter_even(read_data()))
for result in pipeline:
    print(result)  # 输出: 0, 4, 16, 36, 64

注意事项

1.生成器只能迭代一次

gen = (x for x in range(3))
list(gen)  # [0, 1, 2]
list(gen)  # [] - 生成器已耗尽

2.yield from 语法(Python 3.3+)

def chain_generators():
    yield from (x for x in range(3))
    yield from (x for x in range(3, 6))

for value in chain_generators():
    print(value)  # 输出: 0, 1, 2, 3, 4, 5
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐