Python 数据结构与迭代器


Python 数据结构与迭代器详解:从列表到生成器

Python 提供了丰富且高效的数据结构(如 listtupledictset),以及强大的序列操作和惰性计算机制(如 generatoriterator)。掌握这些核心概念,是写出简洁、高效、Pythonic 代码的关键。

本文将系统梳理你日常开发中最常用的数据结构操作,并深入讲解迭代器与生成器的原理与应用。


一、列表(List):最灵活的序列

1. 基础特性

  • 可变、有序、允许重复、支持混合类型。
list1 = [1, 2, 3]
list2 = ['a', 'b', 'v']
list3 = [1, 2, [1, 2, 3]]  # 嵌套

2. 索引与切片

# 正向索引(0 起始)
print(list1[0])   # 1

# 负向索引(-1 为末尾)
print(list2[-1])  # 'v'

# 切片:左闭右开,[start:stop:step]
res = list1[:]          # 全拷贝
res2 = list1[1:3]       # [2, 3]
res3 = list1[1:3:2]     # [2]
print(list1[-1:-3:-1])  # [5, 4](倒序取)

✅ 切片不会修改原列表,而是返回新列表。


3. 增删改查

list1 = [1, 2, 3]

# 增
list1.append(1)           # 末尾添加 → [1,2,3,1]
list1.insert(2, 4)        # 指定位置插入 → [1,2,4,3,1]
list1.extend([2, 3, 4])   # 批量追加元素 → [1,2,4,3,1,2,3,4]

# 删
res = list1.pop(1)        # 删除索引 1 并返回值
list1.remove(3)           # 删除第一个值为 3 的元素
del list1[2]              # 删除索引 2
list1.clear()             # 清空列表

# 改
list1[2] = 10             # 直接赋值更新

4. 常用方法

list1 = [1, 3, 2, 3, 4]

print(list1.index(2))     # 2(首次出现的索引)
print(list1.count(3))     # 2(出现次数)

list1.reverse()           # 原地反转 → [4,3,2,3,1]
list1.sort()              # 原地升序排序
list1.sort(reverse=True)  # 倒序
list1.sort(key=lambda x: -x)  # 自定义排序逻辑

⚠️ 注意:sort() 是原地操作,不返回新列表;若需新列表,请用 sorted(list1)


5. 遍历方式

num = [1, 2, 3]

# 方式1:直接遍历元素
for i in num:
    print(i)

# 方式2:通过索引
for index in range(len(num)):
    print(num[index])

# 方式3:同时获取索引和值(推荐!)
for index, item in enumerate(num):
    print(index, item)

二、元组(Tuple):不可变的序列

  • 不可变、有序、支持索引和切片。
  • 常用于函数返回多个值、作为字典键(因 hashable)。
tp = (1, 2, 3, 4, 5, 6, 7, 8, 9)
tp2 = tuple([1])          # 单元素元组必须加逗号:(1,)

print(tp[1])              # 2
print(tp.index(9))        # 8
print(tp.count(9))        # 1

✅ 优势:比列表更节省内存,线程安全。


三、字典(Dict):键值对映射

scores = {}
scores['A'] = {2, 3, 4}   # 值可以是集合
scores['A'].add(5)

print('A' in scores)      # True
print(scores.get('B'))    # None(安全访问)

# 遍历
for k, v in scores.items():
    print(k, v)

# 或仅遍历键
for score in scores:
    print(score, scores[score])

💡 字典在 Python 3.7+ 保持插入顺序。


四、集合(Set):无序唯一元素容器

1. 基本特性

  • 无序、元素唯一、可变(set)或不可变(frozenset)。
  • 元素必须是可哈希的(不能是 listdict 等可变对象)。
s1 = {1, 2, 3, 4, 4, 3}   # 自动去重 → {1,2,3,4}
s2 = {'a', 'b', 'b', 'c'} # → {'a','b','c'}

# 不可变集合
s4 = frozenset({1, 2, 3})
# s4.add(10)  # ❌ 报错!

2. 增删改查

s1 = {1, 2, 3}

s1.add(4)                 # 添加
s1.update([2, 3, 4])      # 批量添加(自动去重)

s1.remove(4)              # 删除(不存在则报错)
s1.discard(4)             # 删除(不存在不报错)
s1.pop()                  # 随机弹出一个元素
s1.clear()                # 清空

print(4 in s1)            # 成员检查

3. 集合运算(数学操作)

s1 = {1, 2, 3}
s2 = {3, 5, 6}

# 并集
print(s1 | s2)            # {1,2,3,5,6}
# 交集
print(s1 & s2)            # {3}
# 差集(s1 - s2)
print(s1 - s2)            # {1,2}
# 对称差集(无交集部分的并集)
print(s1 ^ s2)            # {1,2,5,6}

✅ 运算符 vs 方法:

  • s1.difference(s2) 等价于 s1 - s2
  • s1.difference_update(s2)原地修改 s1

4. 实用场景:去重

l1 = ['b','c','d','c','a','a']

# 方法1:利用 set(但会丢失顺序)
print(list(set(l1)))      # 顺序不确定

# 方法2:手动去重(保持顺序)
l2 = []
for i in l1:
    if i not in l2:
        l2.append(i)
print(l2)                 # ['b','c','d','a']

🔜 Python 3.7+ 可用 dict.fromkeys(l1) 保持顺序去重。


五、序列通用操作

1. 拼接与重复

list1 = [1, 2]
list2 = [3, 4]

print(list1 + list2)      # [1,2,3,4]
print(list1 * 3)          # [1,2,1,2,1,2]

tp1 = (1, 2)
print(tp1 * 2)            # (1,2,1,2)

print('*****' * 6)        # **************************

2. 解包(Unpacking)

def unpack(*args):
    print(f'类型: {type(args)}, 参数: {args}')

a1 = (1, 2, 3, 4)
a2 = [1, 2, 3, 4, 5]

unpack(*a1)   # (1,2,3,4)
unpack(*a2)   # (1,2,3,4,5)
unpack(a1)    # ((1,2,3,4),) ← 整个元组作为单个参数

* 用于“展开”可迭代对象,常用于函数调用、列表合并等。


六、字符串:也是序列!

字符串支持所有序列操作:

s = 'pumas are large,@cat like animals'

print(s[0])               # 'p'
print(s[-1])              # 's'
print(s[0:3])             # 'pum'
print(s[-3:-1])           # 'al'

# 分割
arr = s.split('@')        # ['pumas are large,', 'cat like animals']
print(type(arr))          # <class 'list'>

# 统计与替换
print(s.count('a'))       # 出现次数
print(s.replace('a', 'c'))

# 去除首尾字符
print(s.strip('123'))     # 若首尾是 '1','2','3' 则去除

# 遍历
for c in s:
    print(c)

七、迭代器(Iterator)与生成器(Generator)

📚 本节内容基于你提供的详细笔记,已做精炼整合。

核心概念关系链:

可迭代对象(Iterable) 
   → iter() → 
迭代器(Iterator) 
   → next() → 
逐个取值

生成器(Generator) 是一种特殊的迭代器。

概念 特点
可迭代对象 实现 __iter__(),如 list, str, dict
迭代器 实现 __iter__()__next__(),只能向前遍历一次
生成器 yield(表达式) 创建,自动实现迭代器协议

1. 生成器函数(使用 yield

def fibonacci(n):
    a, b = 0, 1
    while n > 0:
        yield a
        a, b = b, a + b
        n -= 1

# 使用
for num in fibonacci(5):
    print(num)  # 0, 1, 1, 2, 3

✅ 优势:惰性求值,内存友好,适合大数据流。


2. 生成器表达式

# 列表推导式(立即计算,占内存)
list1 = [n * n for n in fibonacci(10)]

# 生成器表达式(惰性,不占内存)
list2 = (n * n for n in fibonacci(10))

print(list1)  # [0, 1, 1, 4, 9, ...]
for n in list2:
    print(n, end=", ")  # 0, 1, 1, 4, 9, ...

⚠️ 注意:生成器只能遍历一次,用完即废。


3. 实际应用场景

  • 处理大文件

    def read_large_file(path):
        with open(path) as f:
            for line in f:
                yield line.strip()
    
  • 无限序列

    def natural_numbers():
        n = 1
        while True:
            yield n
            n += 1
    
  • 管道式数据处理

    def square(nums): 
        for n in nums: yield n * n
        
    def even_filter(nums): 
        for n in nums: 
            if n % 2 == 0: yield n
    
    data = range(1, 6)
    result = even_filter(square(data))
    print(list(result))  # [4, 16]
    

八、快速排序(Quick Sort)示例

def quick_sort(list1):
    if len(list1) <= 1:
        return list1
    pivot = list1[0]
    left = [x for x in list1[1:] if x < pivot]
    right = [x for x in list1[1:] if x >= pivot]
    return quick_sort(left) + [pivot] + quick_sort(right)

print(quick_sort([1, 2, 3, 9, 8, 4, 5, 6, 7]))
# 输出: [1, 2, 3, 4, 5, 6, 7, 8, 9]

💡 虽然 Python 内置 sorted() 更高效,但手写快排有助于理解分治思想。


总结:数据结构选择指南

需求 推荐类型
有序、可变、允许重复 list
有序、不可变 tuple
键值映射 dict
唯一元素、集合运算 set
大数据流、惰性计算 generator
高性能数值计算 考虑 arraynumpy

🐍 Python 之禅
“There should be one — and preferably only one — obvious way to do it.”
但 Python 也提供了多种工具,让你在不同场景下选择最合适的方式。


希望这篇系统总结能帮助你巩固 Python 数据结构与迭代器的核心知识!动手运行每个示例,尝试修改参数,是掌握它们的最佳途径。欢迎分享你的实践心得!

本文由mdnice多平台发布

posted @ 2026-01-11 15:53  言下忘言  阅读(3)  评论(0)    收藏  举报