Python进阶--生成器(Generator)


一、生成器的核心概念与本质

1. 前置知识:可迭代对象 vs 迭代器

在讲生成器前,必须先搞懂这两个概念(小白必看):

  • 可迭代对象(Iterable) :可以用 for 循环遍历的对象,比如列表 [1,2,3]、字符串 "abc"、字典 {"a":1}
    判断方法 :用 isinstance(obj, Iterable)
  • 迭代器(Iterator) :是可迭代对象的"升级版",可以用 next() 逐个获取元素,直到抛出 StopIteration 异常;
    判断方法 :用 isinstance(obj, Iterator)

关系 :迭代器一定是可迭代对象,但可迭代对象不一定是迭代器(比如列表是可迭代对象,但不是迭代器,需要用 iter() 转换成迭代器)。

复制代码
# 示例:可迭代对象 vs 迭代器
from collections.abc import Iterable, Iterator

my_list = [1, 2, 3]  # 可迭代对象
print(isinstance(my_list, Iterable))  # 输出:True
print(isinstance(my_list, Iterator))  # 输出:False

# 用iter()将可迭代对象转换成迭代器
my_iterator = iter(my_list)
print(isinstance(my_iterator, Iterator))  # 输出:True

# 用next()逐个获取元素
print(next(my_iterator))  # 输出:1
print(next(my_iterator))  # 输出:2
print(next(my_iterator))  # 输出:3
# print(next(my_iterator))  # 报错:StopIteration(没有更多元素了)

2. 什么是生成器?

生成器是一种特殊的迭代器 ,它具备迭代器的所有特性(可以用 next()、可以用 for 循环),但创建方式更简单,且惰性求值(按需生成元素,不一次性占用大量内存)。

英语 :Generator
核心特点

  • 不需要一次性生成所有元素,只在需要时生成下一个;
  • 极大节省内存,适合处理大数据集或无限序列。

二、生成器的两种创建方式

方式1:生成器表达式(Generator Expression)

1. 语法

与列表推导式几乎一样,只是把 [] 换成 ()

复制代码
# 列表推导式:一次性生成所有元素,返回列表
list_comp = [i**2 for i in range(5)]  # 结果:[0, 1, 4, 9, 16]

# 生成器表达式:按需生成元素,返回生成器对象
gen_comp = (i**2 for i in range(5))   # 结果:<generator object <genexpr> at 0x...>
2. 数学结合例子:生成等比数列的前n项

高数背景 :等比数列,首项a₁,公比q,通项公式aₙ = a₁×qⁿ⁻¹;英语:Geometric sequence)

复制代码
a1 = 2  # 首项(First term)
q = 3   # 公比(Common ratio)
n = 5   # 项数(Number of terms)

# 生成器表达式:生成前5项(2, 6, 18, 54, 162)
geometric_gen = (a1 * (q ** i) for i in range(n))

方式2:生成器函数(Generator Function)+ yield 关键字

如果生成器的逻辑比较复杂(需要循环、条件判断、数学计算),就用生成器函数 ,核心是 yield 关键字。

1. yieldreturn 的核心区别(小白必懂)
  • return
    • 执行到 return 时,函数立即结束
    • 一次性返回所有值(如果有的话);
    • 函数执行完毕后,局部变量会被销毁。
  • yield
    • 执行到 yield 时,函数暂停执行,保存当前的所有状态(局部变量、执行位置等);
    • 返回一个值给调用者;
    • 下次调用 next() 时,函数从暂停的位置继续执行 ,直到遇到下一个 yield 或函数结束。
2. 生成器函数的基本语法
复制代码
def 生成器函数名(参数):
    初始化代码
    while 条件:
        yield 要生成的值
        更新状态的代码
3. 生成器函数的执行流程(步骤分解,小白必看)

我们用一个简单的例子,逐步骤讲解生成器函数的执行过程:

复制代码
def count_up_to(n):
    """生成0到n的整数(包含n)"""
    print("--- 生成器函数启动 ---")
    i = 0
    while i <= n:
        print(f"--- 准备生成第 {i+1} 个值 ---")
        yield i  # 暂停点1
        print(f"--- 继续执行,更新i为 {i+1} ---")
        i += 1
    print("--- 生成器函数结束 ---")

现在我们创建生成器对象并调用 next(),逐步骤看发生了什么:

复制代码
# 步骤1:创建生成器对象(注意:此时函数**不会执行**,只是创建了一个对象)
counter = count_up_to(2)
# 此时没有任何输出,因为函数还没启动

# 步骤2:第一次调用next()
print("第一次调用next()的结果:", next(counter))
# 执行流程:
# 1. 进入count_up_to函数,执行print("--- 生成器函数启动 ---")
# 2. i = 0
# 3. 进入while循环(i=0 <= 2,条件成立)
# 4. 执行print(f"--- 准备生成第 {i+1} 个值 ---")
# 5. 遇到yield i:暂停函数,保存当前状态(i=0,执行位置在yield处),返回i=0给调用者
# 输出:
# --- 生成器函数启动 ---
# --- 准备生成第 1 个值 ---
# 第一次调用next()的结果: 0

# 步骤3:第二次调用next()
print("第二次调用next()的结果:", next(counter))
# 执行流程:
# 1. 从上次暂停的位置(yield i之后)继续执行
# 2. 执行print(f"--- 继续执行,更新i为 {i+1} ---")
# 3. i += 1 → i=1
# 4. 回到while循环开头(i=1 <= 2,条件成立)
# 5. 执行print(f"--- 准备生成第 {i+1} 个值 ---")
# 6. 遇到yield i:暂停函数,返回i=1
# 输出:
# --- 继续执行,更新i为 1 ---
# --- 准备生成第 2 个值 ---
# 第二次调用next()的结果: 1

# 步骤4:第三次调用next()
print("第三次调用next()的结果:", next(counter))
# 执行流程类似,最终返回i=2
# 输出:
# --- 继续执行,更新i为 2 ---
# --- 准备生成第 3 个值 ---
# 第三次调用next()的结果: 2

# 步骤5:第四次调用next()
# print("第四次调用next()的结果:", next(counter))
# 执行流程:
# 1. 从暂停处继续,执行print(f"--- 继续执行,更新i为 {i+1} ---")
# 2. i += 1 → i=3
# 3. 回到while循环开头(i=3 <= 2,条件不成立)
# 4. 执行print("--- 生成器函数结束 ---")
# 5. 函数结束,抛出StopIteration异常
4. 数学结合例子:生成泰勒展开式的前n项(高数应用)

高数背景 :eˣ的泰勒展开式为 eˣ = 1 + x + x²/2! + x³/3! + ... + xⁿ/n! + ...;英语:Taylor series)

复制代码
def taylor_exp(x, n_terms):
    """
    近似生成e^x的泰勒展开式的前n_terms项
    :param x: 自变量x
    :param n_terms: 项数
    """
    term = 1  # 第0项:x^0 / 0! = 1
    yield term  # 生成第0项
    
    factorial = 1  # 阶乘,初始为0! = 1
    for k in range(1, n_terms):
        factorial *= k  # 计算k! = (k-1)! × k
        term = (x ** k) / factorial  # 计算第k项:x^k / k!
        yield term  # 生成第k项

# 测试:生成e^2的前5项泰勒展开式
x = 2
n_terms = 5
taylor_gen = taylor_exp(x, n_terms)

# 逐个获取项并累加,近似计算e^2
approx = 0
print(f"e^{x}的泰勒展开式前{n_terms}项:")
for i, term in enumerate(taylor_gen):
    approx += term
    print(f"第{i}项:{term:.6f},当前累加和:{approx:.6f}")

# 实际e^2的值约为7.389056,对比一下
import math
print(f"实际e^{x}的值:{math.exp(x):.6f}")

三、从生成器中获取数据的6种方法(重点)

生成器是迭代器,所以所有迭代器的获取数据方法都适用于生成器,这里详细讲解每一种

方法1:用 next() 逐个获取(最基础)

  • 语法:next(生成器对象)

  • 特点:每次调用返回一个元素,直到生成器耗尽,抛出 StopIteration 异常

  • 适用场景:需要手动控制获取节奏,或只需要前几个元素

    示例:用next()获取等比数列的前3项

    geometric_gen = (2 * (3 ** i) for i in range(5)) # 前5项:2,6,18,54,162

    print(next(geometric_gen)) # 输出:2
    print(next(geometric_gen)) # 输出:6
    print(next(geometric_gen)) # 输出:18

    剩下的54和162还没生成,节省内存

方法2:用 for 循环遍历(最常用,推荐)

  • 语法:for 元素 in 生成器对象:

  • 特点:自动处理 StopIteration 异常,不会报错;遍历完后生成器耗尽,无法再次遍历

  • 适用场景:需要遍历所有元素

    示例:用for循环遍历泰勒展开式生成器

    taylor_gen = taylor_exp(2, 5)

    print("e^2的泰勒展开式前5项:")
    for term in taylor_gen:
    print(term)

方法3:转换成列表/元组/集合(一次性获取所有元素)

  • 语法:list(生成器对象)tuple(生成器对象)set(生成器对象)

  • 特点:一次性生成所有元素并转换成对应数据结构;会失去生成器的内存优势(因为所有元素都加载到内存了)

  • 适用场景:需要将生成器的结果保存为列表等数据结构,且数据量不大

    示例:将生成器转换成列表

    geometric_gen = (2 * (3 ** i) for i in range(5))
    geometric_list = list(geometric_gen)
    print(geometric_list) # 输出:[2, 6, 18, 54, 162]

    注意:转换成列表后,生成器已经耗尽,无法再次使用

    print(next(geometric_gen)) # 报错:StopIteration

方法4:用 next() + 默认值(避免StopIteration异常)

  • 语法:next(生成器对象, 默认值)

  • 特点:当生成器耗尽时,返回默认值,而不是抛出异常

  • 适用场景:不确定生成器是否还有元素,不想处理异常

    示例:用next() + 默认值

    geometric_gen = (2 * (3 ** i) for i in range(3)) # 只有3项:2,6,18

    print(next(geometric_gen, "没有更多元素了")) # 输出:2
    print(next(geometric_gen, "没有更多元素了")) # 输出:6
    print(next(geometric_gen, "没有更多元素了")) # 输出:18
    print(next(geometric_gen, "没有更多元素了")) # 输出:没有更多元素了(不报错)

方法5:用 enumerate() 获取索引和元素(同时知道是第几个元素)

  • 语法:for 索引, 元素 in enumerate(生成器对象):

  • 特点:可以同时获取元素的索引(从0开始)和元素本身

  • 适用场景:需要知道元素的位置

    示例:用enumerate()获取斐波那契数列的索引和元素

    def fibonacci(n):
    a, b = 0, 1
    for _ in range(n):
    yield a
    a, b = b, a + b

    fib_gen = fibonacci(5)
    print("斐波那契数列前5项(带索引):")
    for i, num in enumerate(fib_gen):
    print(f"第{i}项:{num}")

方法6:用 zip() 同时遍历多个生成器

  • 语法:for 元素1, 元素2 in zip(生成器1, 生成器2):

  • 特点:同时遍历多个生成器,每次从每个生成器中取一个元素,直到最短的生成器耗尽

  • 适用场景:需要同时处理多个序列

    示例:用zip()同时遍历两个生成器(生成x和x²的对应关系)

    x_gen = (i for i in range(1, 4)) # 生成1,2,3
    x_square_gen = (i**2 for i in range(1, 4)) # 生成1,4,9

    print("x和x²的对应关系:")
    for x, x_square in zip(x_gen, x_square_gen):
    print(f"{x} → {x_square}")


四、生成器函数的进阶方法:send()/throw()/close()

生成器对象除了 next(),还有三个进阶方法,用于与生成器交互

1. send():向生成器发送值,并获取下一个元素

  • 语法:生成器对象.send(值)
  • 作用:
    1. 向生成器暂停的位置发送一个值,这个值会被赋值给 yield 左边的变量;
    2. 继续执行生成器,直到遇到下一个 yield 或结束;
    3. 返回下一个 yield 的值。
  • 注意:第一次调用生成器时,必须先用 next() send(None)启动生成器 ,不能直接 send(非None值),否则会报错。
数学结合例子:生成可调整公差的等差数列

线代背景 :可以理解为向量的步长调整;英语:Adjustable common difference)

复制代码
def adjustable_arithmetic(a1, initial_d):
    """
    生成可调整公差的等差数列
    :param a1: 首项
    :param initial_d: 初始公差
    """
    current = a1
    d = initial_d
    while True:
        # 暂停,返回current;如果收到send的值,赋值给new_d
        new_d = yield current
        if new_d is not None:
            d = new_d  # 更新公差
        current += d  # 计算下一项

# 测试:生成可调整公差的等差数列
arith_gen = adjustable_arithmetic(a1=1, initial_d=2)

# 第一次必须用next()或send(None)启动
print(next(arith_gen))  # 输出:1(首项)
print(arith_gen.send(None))  # 输出:3(公差2,1+2=3)

# 发送新的公差5
print(arith_gen.send(5))  # 输出:8(公差更新为5,3+5=8)
print(arith_gen.send(None))  # 输出:13(保持公差5,8+5=13)

# 再发送新的公差10
print(arith_gen.send(10))  # 输出:23(公差更新为10,13+10=23)

2. throw():向生成器抛出异常

  • 语法:生成器对象.throw(异常类型, 异常信息)

  • 作用:在生成器暂停的位置抛出指定的异常,生成器可以捕获这个异常并处理;如果生成器没有捕获,异常会传递给调用者。

  • 适用场景:需要在生成器内部处理异常,或强制终止生成器。

    示例:用throw()向生成器抛出异常

    def count_up_to(n):
    i = 0
    while i <= n:
    try:
    yield i
    i += 1
    except ValueError:
    print("生成器捕获到ValueError,继续执行")

    测试

    counter = count_up_to(3)
    print(next(counter)) # 输出:0
    print(next(counter)) # 输出:1

    抛出ValueError

    counter.throw(ValueError, "这是一个测试异常") # 生成器捕获异常,输出提示
    print(next(counter)) # 输出:2(继续执行)

3. close():关闭生成器

  • 语法:生成器对象.close()

  • 作用:关闭生成器,之后再调用 next() 会抛出 StopIteration 异常;生成器关闭时,会在暂停位置抛出 GeneratorExit 异常,生成器可以捕获这个异常进行清理工作。

  • 适用场景:需要提前终止生成器,释放资源。

    示例:用close()关闭生成器

    def count_up_to(n):
    try:
    i = 0
    while i <= n:
    yield i
    i += 1
    except GeneratorExit:
    print("生成器被关闭,进行清理工作")

    测试

    counter = count_up_to(3)
    print(next(counter)) # 输出:0
    print(next(counter)) # 输出:1
    counter.close() # 关闭生成器,输出清理提示

    print(next(counter)) # 报错:StopIteration


五、yield from 语法:生成器的嵌套与委托

1. 什么是 yield from

yield from 是Python 3.3引入的语法,用于委托生成器,即:在一个生成器函数中,调用另一个生成器,并将另一个生成器的所有元素"透传"给调用者。

2. 基本语法

复制代码
def 外层生成器():
    # 委托给内层生成器
    yield from 内层生成器()

3. 不用 yield from vs 用 yield from 的对比

不用 yield from:需要手动循环内层生成器
复制代码
def inner_gen():
    """内层生成器:生成1,2,3"""
    yield 1
    yield 2
    yield 3

def outer_gen():
    """外层生成器:手动循环内层生成器"""
    print("外层生成器启动")
    for num in inner_gen():
        yield num
    print("外层生成器结束")

# 测试
for num in outer_gen():
    print(num)
# 输出:
# 外层生成器启动
# 1
# 2
# 3
# 外层生成器结束
yield from:简化代码,自动透传
复制代码
def inner_gen():
    yield 1
    yield 2
    yield 3

def outer_gen():
    print("外层生成器启动")
    yield from inner_gen()  # 委托给内层生成器,自动透传所有元素
    print("外层生成器结束")

# 测试
for num in outer_gen():
    print(num)
# 输出和上面一样,但代码更简洁

4. yield from 的进阶作用:处理嵌套生成器

如果有多层嵌套的生成器,yield from 可以大大简化代码:

复制代码
# 示例:三层嵌套生成器,用yield from透传
def gen1():
    yield 1
    yield 2

def gen2():
    yield from gen1()
    yield 3
    yield 4

def gen3():
    yield from gen2()
    yield 5

# 测试:直接遍历gen3,就能获取所有元素
for num in gen3():
    print(num)  # 输出:1,2,3,4,5

5. AI结合例子:生成大模型的多轮对话历史

AI场景 :大模型需要处理多轮对话历史,用 yield from 可以分层生成不同角色的对话;英语:Dialogue history)

复制代码
def system_prompt():
    """生成系统提示词"""
    yield {"role": "system", "content": "你是一个Python教学助手,回答要通俗易懂"}

def user_messages(user_inputs):
    """生成用户对话流"""
    for msg in user_inputs:
        yield {"role": "user", "content": msg}

def assistant_messages(assistant_outputs):
    """生成助手对话流"""
    for msg in assistant_outputs:
        yield {"role": "assistant", "content": msg}

def full_dialogue_history(user_inputs, assistant_outputs):
    """拼接完整对话流,惰性生成,不占内存"""
    yield from system_prompt()
    yield from user_messages(user_inputs)
    yield from assistant_messages(assistant_outputs)

# 使用示例
if __name__ == "__main__":
    user_inputs = ["你好", "什么是Python生成器?"]
    assistant_outputs = ["你好!", "生成器是一种用yield返回的迭代器,可以惰性生成数据..."]
    
    # 流式处理对话历史,内存里只有当前一条数据
    print("流式对话历史:")
    for turn in full_dialogue_history(user_inputs, assistant_outputs):
        print(turn)

六、生成器的核心优势:内存节省与惰性求值

1. 内存对比:列表 vs 生成器(直观展示)

我们用 sys.getsizeof() 来实际测量列表和生成器的内存占用:

复制代码
import sys

# 生成100万个整数的平方
n = 10**6

# 用列表:一次性生成所有元素
my_list = [i**2 for i in range(n)]
print(f"列表的内存占用:{sys.getsizeof(my_list) / 1024 / 1024:.2f} MB")

# 用生成器:按需生成
my_gen = (i**2 for i in range(n))
print(f"生成器的内存占用:{sys.getsizeof(my_gen)} 字节")

输出结果(不同机器可能略有不同):

复制代码
列表的内存占用:约8.44 MB
生成器的内存占用:约128 字节

可以看到,生成器的内存占用几乎可以忽略不计,而列表随着数据量增大,内存占用会线性增长。

2. 惰性求值(Lazy Evaluation)

惰性求值是生成器的核心特性,即:只有当调用 next() for循环时,才会生成下一个元素,之前的元素如果没有保存,就会被丢弃(除非用列表等保存)。

好处

  • 可以处理无限序列(比如所有正整数、所有斐波那契数),因为不需要一次性生成所有元素;
  • 节省内存,适合处理大数据集(比如几GB的文件、AI训练数据)。
例子:生成无限的正整数序列
复制代码
def infinite_integers():
    """生成无限的正整数序列:1,2,3,4,..."""
    i = 1
    while True:
        yield i
        i += 1

# 测试:只获取前5个元素(不会生成无限个,节省内存)
inf_gen = infinite_integers()
for _ in range(5):
    print(next(inf_gen))  # 输出:1,2,3,4,5

七、生成器的实战应用(含AI/数学场景)

应用1:大文件读取(避免一次性加载到内存)

如果有一个几GB的日志文件,用列表一次性读取会导致内存溢出,用生成器可以逐行读取:

复制代码
def read_large_file(file_path):
    """
    逐行读取大文件
    :param file_path: 文件路径
    """
    with open(file_path, 'r', encoding='utf-8') as f:
        for line in f:
            yield line.strip()  # 逐行生成,去掉换行符

# 测试:逐行处理大文件(比如统计包含"error"的行数)
error_count = 0
for line in read_large_file("large_log.txt"):
    if "error" in line:
        error_count += 1
print(f"包含'error'的行数:{error_count}")

应用2:AI大模型的流式文本生成(逐字输出)

AI场景 :大模型生成文本时,通常是逐字生成的,用生成器可以实现流式输出,让用户实时看到生成的内容;英语:Streaming output)

复制代码
import time

def llm_text_generator(prompt):
    """
    模拟大模型的流式文本生成
    :param prompt: 用户输入的提示词
    """
    # 模拟大模型生成的文本(实际中是从模型接口获取的)
    generated_text = f"你输入的提示词是:{prompt}。生成器非常适合大模型的流式输出,因为它可以逐字生成内容,让用户实时看到结果。"
    
    # 逐字生成(模拟大模型的生成延迟)
    for char in generated_text:
        time.sleep(0.05)  # 模拟生成延迟,每0.05秒生成一个字
        yield char

# 测试:模拟大模型的流式输出
prompt = "请介绍生成器在AI中的应用"
print("大模型正在生成:", end="", flush=True)
for char in llm_text_generator(prompt):
    print(char, end="", flush=True)  # 逐字输出,不换行
print()

应用3:线代中的矩阵逐行生成(处理大矩阵)

线代背景 :处理大矩阵时,用生成器可以逐行生成,避免一次性占用大量内存;英语:Matrix row generation)

复制代码
import random

def matrix_generator(rows, cols):
    """
    逐行生成一个rows行cols列的随机矩阵
    :param rows: 行数
    :param cols: 列数
    """
    for _ in range(rows):
        # 生成一行:cols个0-1之间的随机数
        row = [random.random() for _ in range(cols)]
        yield row

# 测试:生成一个3行4列的矩阵,并逐行处理
matrix_gen = matrix_generator(3, 4)
print("逐行生成的矩阵:")
for i, row in enumerate(matrix_gen):
    print(f"第{i}行:{[round(x, 2) for x in row]}")  # 保留两位小数

应用4:高数中的无限级数求和(按需计算项数)

高数背景 :无限级数求和时,用生成器可以按需生成项,直到达到精度要求;英语:Infinite series summation)

复制代码
def harmonic_series():
    """生成调和级数的项:1/1, 1/2, 1/3, 1/4, ..."""
    n = 1
    while True:
        yield 1 / n
        n += 1

# 测试:计算调和级数的前n项和,直到和超过5
harmonic_gen = harmonic_series()
sum_harmonic = 0
n_terms = 0
while sum_harmonic <= 5:
    sum_harmonic += next(harmonic_gen)
    n_terms += 1
print(f"调和级数前{n_terms}项和超过5,和为:{sum_harmonic:.6f}")

应用5:自定义数据加载器, 分批次获取数据, 模拟: 后续分批次训练模型.

复制代码
import math
# 需求: 已知文件中记录的是所有的歌词数据, 请自定义数据加载器, 接收 条数/批次, 分批次获取数据.
# todo 1.定义函数, 获取所有批次的数据 -> 封装到 生成器对象中.
def get_dataloader(batch_size):
    """
    该函数用于 按照指定的批次大小, 分批次获取数据, 并封装到 生成器对象中.
    :param batch_size: 批次大小, 例如: 8条/批
    :return: 生成器对象
    """
    # 1. 一次性从文件中读取所有的数据, 并封装到列表中.
    with open('./data/jaychou_lyrics.txt', 'r', encoding='utf-8') as src_f:
        lines = src_f.readlines()       # 格式为: ['第1行\n', '第2行\n', '第3行\n', ...]

    # 2. 获取总数据条数.
    total_size = len(lines)     # 5819条
    # 3. 计算总批次数.
    # 思路1: 调用 math模块的ceil()函数, 简写为:  math#ceil()
    # total_batch = math.ceil(total_size / batch_size)
    # print(total_batch)

    # 思路2: 自己推导公式, 总批次数 = (数据总数 + 每批次的数据条数 - 1) // 每批次的数据条数
    total_batch = (total_size + batch_size - 1) // batch_size           # 728批

    # 4. 遍历, 具体的获取每一批次数据, 然后封装到生成器中.
    for i in range(total_batch):        # i是批次索引, 从0开始 -> 第1批,   1 -> 第2批...
        # 思考: 每批次的数据具体如何获取?
        # 第0批次: lines[0:8]
        # 第1批次: lines[8:16]
        # 第i批次: lines[i * batch_size: i * batch_size + batch_size]
        yield lines[i * batch_size: i * batch_size + batch_size]        # yield三件事: 创建, 添加, 返回


# todo 2.调用函数.
my_generator = get_dataloader(8)
print(my_generator, type(my_generator))     # <class 'generator'>
print('-' * 30)

# 获取第1批次的数据.
print(next(my_generator))

# 获取第2批次的数据.
print(next(my_generator))

学习总结

  1. 生成器的本质:特殊的迭代器,惰性求值,节省内存;
  2. 两种创建方式
    • 简单逻辑:生成器表达式 (...)
    • 复杂逻辑:生成器函数 + yield
  1. 获取数据的6种方法next()for 循环、转换成列表/元组、next(, 默认值)enumerate()zip()
  2. 进阶方法send()(传值)、throw()(抛异常)、close()(关闭);
  3. yield from:委托生成器,简化嵌套;
  4. 实战应用:大文件读取、AI流式输出、矩阵生成、无限级数求和。
相关推荐
2301_814809862 小时前
如何用 cookie 的 HttpOnly 与 Secure 属性防范 XSS 攻击
jvm·数据库·python
李松桃2 小时前
实战:手刃豆瓣电影TOP250
python·爬虫实战·requests·re
m0_515098422 小时前
如何用 Object.keys 与 getOwnPropertyNames 遍历键名
jvm·数据库·python
databook2 小时前
如何让多个动画“齐步走”?
python·数学·动效
qq_189807032 小时前
golang如何实现日志按级别过滤_golang日志按级别过滤实现教程
jvm·数据库·python
abc123456sdggfd2 小时前
Golang map底层实现原理_Golang map哈希表原理教程【经典】
jvm·数据库·python
yaoxin5211232 小时前
391. Java 文件操作基础 - 方法链式调用
java·开发语言·python
justjinji2 小时前
JavaScript中利用宏任务拆分阻塞任务的实操案例
jvm·数据库·python
weixin_408717772 小时前
c++如何实现跨平台的文件读写进度监听器回调机制【实战】
jvm·数据库·python