返回博客

18. 高级特性:切片、迭代与列表生成式

18. 高级特性:切片、迭代与列表生成式

第十八篇:高级特性——切片、迭代与列表生成式

前言

本文全面讲解 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 高级特性的核心知识:

  1. 切片 — seq[start:stop:step]、反转、切片赋值
  2. 可迭代对象 — iter()/next() 原理、自定义迭代器、for 循环内部机制
  3. 列表生成式 — 基本语法、条件过滤、嵌套循环、多维操作
  4. 字典/集合推导式 — 简洁高效的创建方式
  5. 生成器表达式 — 惰性计算、内存友好、链式管道
  6. itertools — count/cycle/repeat/chain/groupby/permutations/combinations
  7. 性能优化 — 生成式比 append 快 20%-40%,生成器比列表省百万倍内存

下一篇文章将深入讲解生成器与迭代器:惰性计算的力量。


本文是 Python 教程系列的第十八篇。