Python 列表推导与生成器

18.1 列表推导式进阶

嵌套推导式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 二维列表展平
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [num for row in matrix for num in row]
print(flat) # [1, 2, 3, 4, 5, 6, 7, 8, 9]

# 矩阵转置
transposed = [[row[i] for row in matrix] for i in range(3)]
print(transposed)
# [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

# 过滤嵌套
numbers = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
evens = [num for row in numbers for num in row if num % 2 == 0]
print(evens) # [2, 4, 6, 8]

复杂条件

1
2
3
4
5
6
7
8
9
10
# 多条件过滤
numbers = range(1, 50)
result = [x for x in numbers if x % 3 == 0 or x % 5 == 0]
print(result)

# 条件表达式
scores = [85, 42, 90, 38, 76, 55]
grades = ["及格" if s >= 60 else "不及格" for s in scores]
print(grades)
# ['及格', '不及格', '及格', '不及格', '及格', '不及格']

18.2 字典与集合推导式

字典推导式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 基本用法
squares = {x: x**2 for x in range(1, 6)}
print(squares) # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

# 键值交换
original = {"a": 1, "b": 2, "c": 3}
swapped = {v: k for k, v in original.items()}
print(swapped) # {1: 'a', 2: 'b', 3: 'c'}

# 过滤
scores = {"Alice": 85, "Bob": 42, "Charlie": 90, "David": 38}
passed = {k: v for k, v in scores.items() if v >= 60}
print(passed) # {'Alice': 85, 'Charlie': 90}

# 统计
text = "hello world"
char_count = {char: text.count(char) for char in set(text)}
print(char_count)

集合推导式

1
2
3
4
5
6
7
8
9
10
11
12
# 基本用法
squares = {x**2 for x in range(1, 6)}
print(squares) # {1, 4, 9, 16, 25}

# 过滤
evens = {x for x in range(20) if x % 2 == 0}
print(evens) # {0, 2, 4, 6, 8, 10, 12, 14, 16, 18}

# 去重处理
words = ["hello", "world", "python", "hello"]
lengths = {len(w) for w in words}
print(lengths) # {5, 6}

18.3 生成器表达式

生成器表达式语法类似列表推导式,但使用圆括号。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 列表推导式 vs 生成器表达式
list_comp = [x**2 for x in range(5)]
gen_expr = (x**2 for x in range(5))

print(list_comp) # [0, 1, 4, 9, 16]
print(gen_expr) # <generator object>

# 遍历生成器
for val in gen_expr:
print(val, end=" ") # 0 1 4 9 16

# 转换为列表
gen = (x**2 for x in range(5))
squares = list(gen)
print(squares) # [0, 1, 4, 9, 16]

内存对比

1
2
3
4
5
6
7
import sys

list_comp = [x for x in range(10000)]
gen_expr = (x for x in range(10000))

print(sys.getsizeof(list_comp)) # ~87616 字节
print(sys.getsizeof(gen_expr)) # ~112 字节

18.4 yield 与生成器函数

基本生成器

1
2
3
4
5
6
7
8
9
10
11
12
13
def count_up_to(max):
count = 1
while count <= max:
yield count
count += 1

counter = count_up_to(5)
print(next(counter)) # 1
print(next(counter)) # 2

# 遍历
for num in count_up_to(3):
print(num) # 1, 2, 3

无限生成器

1
2
3
4
5
6
7
8
9
def infinite_counter():
count = 0
while True:
yield count
count += 1

counter = infinite_counter()
for _ in range(5):
print(next(counter)) # 0, 1, 2, 3, 4

斐波那契生成器

1
2
3
4
5
6
7
8
9
10
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b

fib = fibonacci()
for _ in range(10):
print(next(fib), end=" ")
# 0 1 1 2 3 5 8 13 21 34

18.5 生成器管道

生成器可以链式组合,形成数据处理管道。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def read_data(filename):
with open(filename) as f:
for line in f:
yield line.strip()

def filter_lines(lines, keyword):
for line in lines:
if keyword in line:
yield line

def transform(lines):
for line in lines:
yield line.upper()

# 使用管道
lines = read_data("log.txt")
filtered = filter_lines(lines, "ERROR")
result = transform(filtered)

for line in result:
print(line)

18.6 生成器方法

send() - 发送值

1
2
3
4
5
6
7
8
9
10
11
12
def accumulator():
total = 0
while True:
value = yield total
if value is not None:
total += value

acc = accumulator()
next(acc) # 启动生成器
print(acc.send(10)) # 10
print(acc.send(20)) # 30
print(acc.send(30)) # 60

throw() - 抛出异常

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def generator():
try:
yield 1
yield 2
yield 3
except ValueError:
print("捕获到 ValueError")
yield -1

gen = generator()
print(next(gen)) # 1
print(next(gen)) # 2
gen.throw(ValueError) # 触发异常
print(next(gen)) # -1

close() - 关闭生成器

1
2
3
4
5
6
7
8
9
10
11
def generator():
try:
yield 1
yield 2
finally:
print("生成器已关闭")

gen = generator()
print(next(gen))
gen.close()
# 输出: 生成器已关闭

18.7 迭代器协议

实现 __iter____next__ 方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Counter:
def __init__(self, max):
self.max = max
self.current = 0

def __iter__(self):
return self

def __next__(self):
if self.current >= self.max:
raise StopIteration
value = self.current
self.current += 1
return value

counter = Counter(5)
for num in counter:
print(num) # 0, 1, 2, 3, 4

18.8 本章小结

  • 列表推导式:[表达式 for 变量 in 可迭代对象 if 条件]
  • 字典/集合推导式语法类似
  • 生成器表达式使用 (),惰性求值节省内存
  • yield 创建生成器函数
  • 生成器支持 send()throw()close()
  • 迭代器协议:__iter____next__

练习题

  1. 使用列表推导式生成 100 以内所有素数
  2. 使用生成器实现无限自然数序列
  3. 使用字典推导式统计字符串中每个字符出现次数
  4. 以下代码输出什么?
    1
    2
    3
    gen = (x for x in range(3))
    print(list(gen))
    print(list(gen))
ByteFisher
分享编程技术 · 记录钓鱼乐趣
扫码关注
▸ 扫码关注 ◂
Python基础教程 系列
第 18/20 篇
分享: