Python 进阶 - 第十九节
📋 本节要点
| 知识点 | 说明 |
|---|---|
| 可迭代对象 | 可用 for 循环遍历的对象(列表、字符串等) |
| 迭代器 | 可通过 iter()/next() 逐个取值的对象 |
| 生成器 | 使用 yield 的特殊迭代器,按需生成数据 |
| 列表推导式 | [] 快速创建列表,立即生成所有数据 |
| 生成器表达式 | () 按需生成,节省内存 |
1. 可迭代对象 vs 迭代器
可迭代对象(Iterable)是可以用 for 循环遍历的对象,如 list、tuple、dict、str 等。
迭代器(Iterator)是真正逐个返回数据的对象,通过 iter() 将可迭代对象转为迭代器,用 next() 取值,遍历完抛出 StopIteration。
from collections.abc import Iterable
# 检查是否为可迭代对象
print(isinstance([], Iterable)) # True
print(isinstance("abc", Iterable)) # True
print(isinstance(123, Iterable)) # False(整数不可迭代)
# 迭代器使用
my_list = [1, 2, 3] # 可迭代对象
it = iter(my_list) # 获取迭代器
print(next(it)) # 1
print(next(it)) # 2
print(next(it)) # 3
# print(next(it)) # StopIteration 异常(已遍历完)
2. 列表推导式
列表推导式(也称列表生成式)用简洁的语法快速创建列表,立即生成所有数据。
# 普通方式创建列表
L = []
for x in range(1, 11):
L.append(x * x)
print(L) # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
# 列表推导式(一行搞定)
M = [x * x for x in range(1, 11)]
print(M) # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
# 带条件的列表推导式
N = [x * x for x in range(1, 11) if x % 2 == 0]
print(N) # [4, 16, 36, 64, 100]
3. 生成器
生成器是一种特殊的迭代器,使用 yield 关键字。调用生成器函数不会立即执行,而是返回一个生成器对象,通过 next() 获取值,每次执行到 yield 暂停,下次从暂停处继续。
3.1 生成器表达式
类似列表推导式,但用 () 替代 [],返回生成器对象,按需生成,节省内存。
# 列表推导式(立即生成所有内容)
M = [x * x for x in range(1, 11)]
print(M) # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
# 生成器表达式(按需生成)
O = (x * x for x in range(1, 11))
print(O) # <generator object ...>
# 用 for 循环遍历生成器
for i in O:
print(i, end=" ") # 1 4 9 16 25 36 49 64 81 100
3.2 生成器函数
用 def 定义生成器,内部使用 yield 暂停并返回值。
def my_generator():
yield 1
yield 2
yield 3
# 创建生成器对象
gen = my_generator()
# 用 next() 逐个取值
print(next(gen)) # 1
print(next(gen)) # 2
print(next(gen)) # 3
# print(next(gen)) # StopIteration
# 也可以用 for 循环遍历
def my_generator():
yield 1
yield 2
yield 3
for i in my_generator():
print(i) # 1 2 3
4. 实战:斐波那契数列
用生成器实现斐波那契数列,每次只生成一个数,按需计算。
def fibonacci(n):
a, b = 0, 1
for _ in range(n):
yield a
a, b = b, a + b
# 使用 for 循环遍历
for num in fibonacci(10):
print(num, end=" ") # 0 1 1 2 3 5 8 13 21 34
5. 实战:生成器读取大文件
读取大文件时,一次性加载会耗尽内存,生成器一次只读一行:
def read_lines(file_path):
"""逐行读取文件,每次只返回一行"""
with open(file_path, 'r', encoding='utf-8') as f:
for line in f:
yield line.strip()
# 处理超大日志文件,内存占用恒定
for line in read_lines("huge_log.txt"):
process(line) # 每次只处理一行
下一节预告:函数式编程
评论区
0 条暂时还没有评论,欢迎来抢沙发。