今天聊一个 Python 中容易被忽视,但超级强大的关键字——yield。很多初学者第一次看到 yield 的时候一脸懵:defcount_up_to(n): for i inrange(n): yield i
这啥玩意儿?return 不好用吗?别急,看完这篇文章,你会惊呼:原来之前错过了这么多!defget_all_numbers(n): result = []for i inrange(n): result.append(i)return result# 当 n = 1000 万时...numbers = get_all_numbers(10_000_000)print(f"内存占用: {numbers.__sizeof__()} bytes") # 约 80MB!
你的电脑吭哧吭哧跑了半天,内存直接爆表。但如果用 yield:defgenerate_numbers(n): for i inrange(n): yield i# 内存占用几乎为零!gen = generate_numbers(10_000_000)print(next(gen)) # 0print(next(gen)) # 1
二、yield 是什么?——"懒惰的厨师"类比
- 普通函数 = 厨师一次性把所有菜做完,再一起端上来(占用大量盘子)
- yield 生成器 = 厨师做完一道,端上来一道(随吃随做,节省资源)
这就是 yield 的核心思想:不一次性返回所有结果,而是返回一个"能产生结果的对象",什么时候要,什么时候给你。def simple_generator(): print("开始执行...") yield 1 print("继续执行...") yield 2 print("再次执行...") yield 3 print("结束")# 使用方式gen = simple_generator()print(next(gen)) # 输出: 1print(next(gen)) # 输出: 2print(next(gen)) # 输出: 3
# ✅ 使用 yield:内存友好!def generate_numbers(n): for i in range(n): yield i# 即使 n = 100,000,000,内存占用几乎不变gen = generate_numbers(100_000_000)print(next(gen)) # 0print(next(gen)) # 1# 只在需要时才计算下一个值
def read_large_file(file_path): """逐行读取大文件,不会爆内存""" with open(file_path, 'r', encoding='utf-8') as f: for line in f: # 可以在这里做预处理 if line.strip(): # 跳过空行 yield line.strip()# 使用示例:分析 10GB 日志文件for line in read_large_file('access.log'): if 'ERROR' in line: print(f"发现错误: {line}")
def fibonacci(): """ 无限生成斐波那契数列 yield 的强大之处:可以表示无限序列! """ a, b = 0, 1 while True: # 无限循环,但不会卡死 yield b a, b = b, a + b# 取前 10 个斐波那契数fib = fibonacci()for _ in range(10): print(next(fib()), end=' ')# 输出: 1 1 2 3 5 8 13 21 34 55
def read_data(source): """数据源""" for item in source: yield itemdef filter_even(numbers): """过滤偶数""" for num in numbers: if num % 2 == 0: yield numdef square(numbers): """平方运算""" for num in numbers: yield num ** 2# 组合成管道data = range(10)pipeline = square(filter_even(read_data(data)))print(list(pipeline))# 输出: [0, 4, 16, 36, 64]
一句话总结,yield 让你的函数变成"智能工厂",不再一次性产出所有产品,而是"要一个做一个",既省空间又灵活!