第十八篇:高级特性——切片、迭代与列表生成式
前言
本文全面讲解 Python 的高级特性:切片操作的灵活用法、可迭代对象与 for 循环的关系、列表生成式的简洁写法,以及多层循环与条件过滤的实用技巧。掌握这些知识后,你将能够用极其简洁的代码处理复杂的数据操作。
切片操作的深入理解
基本语法:seq[start:stop:step]
nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# start 省略 → 从头开始
print(nums[:5]) # [0, 1, 2, 3, 4]
# stop 省略 → 到末尾结束
print(nums[5:]) # [5, 6, 7, 8, 9]
# step 为正 → 从左向右取
print(nums[::2]) # [0, 2, 4, 6, 8] — 每隔一个取一个
# step 为负 → 从右向左取(反转)
print(nums[::-1]) # [9, 8, 7, ..., 0] — 反转列表
字符串切片与 bytes 切片
# 字符串切片同样适用
text = "Hello, World!"
print(text[0:5]) # Hello
print(text[7:]) # World!
print(text[::-1]) # !dlroW ,olleH
print(text[::2]) # Hlo ol! — 每隔一个字符
# bytes 切片
data = b"Python"
print(data[0:3]) # b'Pyt'
print(data[::-1]) # b'nohtyP'
切片赋值(原地修改)
nums = [1, 2, 3, 4, 5]
# 替换指定范围
nums[1:3] = [10, 20]
print(nums) # [1, 10, 20, 4, 5]
# 插入元素(start == stop)
nums[2:2] = [30, 40]
print(nums) # [1, 10, 30, 40, 20, 4, 5]
# 删除元素(用空列表替换)
del nums[2:5]
print(nums) # [1, 10, 5]
# ⚠️ 长度不匹配时列表自动伸缩
nums = [1, 2, 3, 4, 5]
nums[1:3] = [10, 20, 30, 40] # 2 个变成 4 个
print(nums) # [1, 10, 20, 30, 40, 4, 5]
浅拷贝 vs 深拷贝
import copy
original = [[1, 2], [3, 4]]
# ✅ 切片是浅拷贝,但嵌套对象仍是引用
copy_by_slice = original[:]
deep_copy = copy.deepcopy(original)
# 对于不可变元素的列表,效果相同
a = [1, 2, 3]
b = a[:]
a[0] = 99
print(b) # [1, 2, 3] — 不受影响
# ❌ 嵌套对象仍会互相影响
nested_a = [[1, 2], [3, 4]]
nested_b = nested_a[:] # 浅拷贝
nested_a[0][0] = 99
print(nested_b) # [[99, 2], [3, 4]] — 被影响了!
可迭代对象与迭代器
什么是可迭代对象?
任何可以用 for 循环遍历的对象都是可迭代对象(iterable):
# 常见可迭代对象
types = [range, list, tuple, str, dict, set, frozenset, bytes]
for t in types:
print(f"{t.__name__}: 支持迭代")
iter() 与 next()
my_list = ["a", "b", "c"]
# iter() 获取迭代器
iterator = iter(my_list)
# next() 逐个获取元素
print(next(iterator)) # a
print(next(iterator)) # b
print(next(iterator)) # c
# next() 可以设置默认值防止 StopIteration 异常
print(next(iterator, None)) # None — 没有更多元素
# 手动实现迭代
try:
while True:
item = next(iterator)
print(item)
except StopIteration:
pass
for 循环的内部机制
# for x in iterable 的实际执行步骤:
# 1. 调用 iter(iterable) 获取迭代器
# 2. 反复调用 next(iterator),将结果赋值给 x
# 3. 捕获 StopIteration 异常,退出循环
# 等价于
it = iter([1, 2, 3])
while True:
try:
x = next(it)
print(x)
except StopIteration:
break
自定义可迭代对象
class FibonacciIterable:
"""自定义斐波那契数列迭代器"""
def __init__(self, max_count):
self.max_count = max_count
self.count = 0
self.a, self.b = 0, 1
def __iter__(self):
return self
def __next__(self):
if self.count >= self.max_count:
raise StopIteration
result = self.a
self.a, self.b = self.b, self.a + self.b
self.count += 1
return result
fib = FibonacciIterable(10)
for num in fib:
print(num, end=" ")
# 输出:0 1 1 2 3 5 8 13 21 34
列表推导式(List Comprehensions)
基本语法
# 传统方式
squares = []
for x in range(10):
squares.append(x ** 2)
# 列表生成式(一行搞定)
squares = [x ** 2 for x in range(10)]
print(squares) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
带条件的生成式
# 过滤偶数
evens = [x for x in range(20) if x % 2 == 0]
print(evens) # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
# 条件转换:奇数保留,偶数翻倍
mixed = [x * 2 if x % 2 == 0 else x for x in range(1, 11)]
print(mixed) # [1, 4, 3, 8, 5, 12, 7, 16, 9, 20]
# 多个条件
primes = []
for num in range(2, 30):
is_prime = all(num % i != 0 for i in range(2, int(num ** 0.5) + 1))
if is_prime:
primes.append(num)
print(primes) # [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
嵌套生成式(笛卡尔积)
# 两个循环
pairs = [(x, y) for x in range(3) for y in range(3)]
print(pairs) # [(0,0), (0,1), (0,2), (1,0), ..., (2,2)]
# 矩阵转置
matrix = [[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]]
# 扁平化二维列表
flat = [item for row in [[1, 2], [3, 4], [5, 6]] for item in row]
print(flat) # [1, 2, 3, 4, 5, 6]
字典/集合/元组推导式
# 字典推导式
upper_dict = {k.upper(): v for k, v in {"name": "小明", "age": 25}.items()}
print(upper_dict) # {'NAME': '小明', 'AGE': 25}
# 集合推导式
unique_lengths = {len(word) for word in ["apple", "banana", "kiwi"]}
print(unique_lengths) # {4, 5, 6}
# 元组推导式 → 返回生成器(不是元组!)
gen = (x ** 2 for x in range(5))
print(gen) # <generator object <genexpr> at 0x...>
print(tuple(gen)) # (0, 1, 4, 9, 16)
生成器表达式
懒计算 vs 内存效率
import sys
# 列表生成式:立即生成所有数据,占用内存大
list_comp = [x ** 2 for x in range(1_000_000)]
print(sys.getsizeof(list_comp)) # ~8 MB
# 生成器表达式:惰性计算,按需生产,内存几乎为零
gen_exp = (x ** 2 for x in range(1_000_000))
print(sys.getsizeof(gen_exp)) # 112 bytes — 极小!
链式生成器
def take(n, iterator):
"""取前 n 个元素"""
for _ in range(n):
yield next(iterator)
# 链式管道
nums = (x for x in range(100))
doubled = (x * 2 for x in nums)
filtered = (x for x in doubled if x % 4 == 0)
result = take(5, filtered)
print(list(result)) # [0, 8, 16, 24, 32]
内置迭代工具 itertools
常用函数速查
| 函数 | 功能 | 示例 |
|---|---|---|
count() |
无限计数 | count(10) → 10, 11, 12... |
cycle() |
循环迭代 | cycle([1,2]) → 1, 2, 1, 2... |
repeat() |
重复迭代 | repeat("A", 3) → A, A, A |
chain() |
连接序列 | chain([1,2], [3,4]) → 1,2,3,4 |
groupby() |
分组 | 按某键分组 |
islice() |
切片迭代 | islice(range(10), 2, 5) → 2,3,4 |
permutations() |
排列 | permutations("ABC") → ABC, ACB, BCA... |
combinations() |
组合 | combinations("ABCDE", 3) → ABC, ABD, ACE... |
实战示例
from itertools import chain, permutations, combinations
# chain — 连接多个可迭代对象
for item in chain(["a", "b"], [1, 2], ["x", "y"]):
print(item, end=" ")
# 输出:a b 1 2 x y
# permutations — 全排列
for perm in permutations("ABC"):
print("".join(perm), end=", ")
# 输出:ABC, ACB, BAC, BCA, CAB, CBA
# combinations — 组合(不考虑顺序)
for combo in combinations("ABCDE", 3):
print("".join(combo), end=", ")
# 输出:ABC, ABD, ABE, ACD, ACE, ADE, BCD, BCE, BDE, CDE
性能对比
列表生成式 vs 普通 for 循环
import timeit
n = 100_000
def loop_approach():
result = []
for x in range(n):
if x % 2 == 0:
result.append(x ** 2)
return result
def comp_approach():
return [x ** 2 for x in range(n) if x % 2 == 0]
loop_time = timeit.timeit(loop_approach, number=100)
comp_time = timeit.timeit(comp_approach, number=100)
print(f"循环方式:{loop_time:.2f}s")
print(f"生成式:{comp_time:.2f}s")
print(f"生成式快 {loop_time/comp_time:.1f} 倍")
# 通常生成式比 append 循环快 20%-40%
生成器 vs 列表
import sys
large_list = [x for x in range(1_000_000)]
large_gen = (x for x in range(1_000_000))
print(sys.getsizeof(large_list)) # ~8 MB
print(sys.getsizeof(large_gen)) # ~112 bytes
总结
本文涵盖了 Python 高级特性的核心知识:
- 切片 — seq[start:stop:step]、反转、切片赋值
- 可迭代对象 — iter()/next() 原理、自定义迭代器、for 循环内部机制
- 列表生成式 — 基本语法、条件过滤、嵌套循环、多维操作
- 字典/集合推导式 — 简洁高效的创建方式
- 生成器表达式 — 惰性计算、内存友好、链式管道
- itertools — count/cycle/repeat/chain/groupby/permutations/combinations
- 性能优化 — 生成式比 append 快 20%-40%,生成器比列表省百万倍内存
下一篇文章将深入讲解生成器与迭代器:惰性计算的力量。
本文是 Python 教程系列的第十八篇。
