Python康复训练——数据结构

目录

  • 一、四种内置数据结构总览
  • [二、列表 list:可变的有序容器](#二、列表 list:可变的有序容器)
  • [三、元组 tuple:不可变的"常量序列"](#三、元组 tuple:不可变的"常量序列")
  • [四、字典 dict:键值对的查找表](#四、字典 dict:键值对的查找表)
  • [五、序列:list / tuple / str 的共同语言](#五、序列:list / tuple / str 的共同语言)
  • [六、集合 set:去重与集合运算](#六、集合 set:去重与集合运算)
  • [七、引用陷阱:= 是"贴标签"不是"复制"](#七、引用陷阱:= 是"贴标签"不是"复制")

一、四种内置数据结构总览

为什么 Python 不直接给一个"万能容器"?因为不同场景对数据的增删频率、查找方式、是否允许改动要求完全不同。专门的结构各管一摊,用对了既快又清晰。

结构 可变 有序 元素约束 典型用途
list 列表 任意对象 动态有序集合(购物车、待办列表)
tuple 元组 任意对象 不可变配置、函数多返回值
dict 字典 ✅(值) 键必须不可变且唯一 键值映射(联系人、配置项)
set 集合 元素必须可哈希(不可变) 去重、交集/并集/差集运算

一句话记忆:列表管"排队",元组管"定值",字典管"查名字",集合管"去重和算关系"


二、列表 list:可变的有序容器

为什么用它

程序里最常见的需求就是"维护一组会变化、且保持先后次序的数据"------购物清单、日志、待处理任务。列表同时满足两点:有序 (按索引取)和可变(原地增删改),所以最常用。

创建与基本操作

python 复制代码
# data_structures/list_demo.py
fruits = ['pear', 'orange', 'apple', 'banana']

# 增:末尾追加 / 指定位置插入
fruits.append('melon')      # ['pear', 'orange', 'apple', 'banana', 'melon']
fruits.insert(0, 'berry')   # 插到索引 0:['berry', 'pear', ...]

# 删:三种姿势
fruits.pop()        # 默认删最后一个,返回被删元素
fruits.pop(1)       # 删索引 1
fruits.remove('apple')  # 删第一个匹配的值,找不到抛 ValueError
del fruits[2]      # 按索引删,等价于 pop(2) 但不返回值

# 改:直接按索引赋值
fruits[0] = 'red apple'

# 查与排序
print(fruits[2])    # 索引访问
fruits.sort()       # 原地排序(返回 None)
fruits.reverse()    # 原地反转

要点:

  • list 用方括号 [] 创建,元素类型可以混搭(但不推荐混,除非真需要)。
  • append 是 O(1),insert(0, ...) 是 O(n)(要挪后面所有元素),高频头插别用列表。
  • sort() / reverse()原地操作 ,不返回新列表------写成 x = fruits.sort() 会得到 None

常用方法速查

方法 作用 备注
append(x) 末尾追加 O(1)
insert(i, x) 索引 i 处插入 O(n)
pop([i]) 删索引 i(默认末尾) 返回被删元素
remove(x) 删第一个值为 x 的项 找不到报错
index(x) 返回 x 首次出现的索引 找不到报错
count(x) 统计 x 出现次数 ---
sort() / reverse() 原地排序 / 反转 不返回新列表
clear() 清空 ---

小结 :列表是"可变有序"的万金油容器。记住 append 快、insert(0) 慢、sort/reverse 原地不动返回 None 这三点,就避开了 80% 的坑。


三、元组 tuple:不可变的"常量序列"

为什么有 list 还要 tuple

列表什么都能改,但有些数据就不该被改 :一个二维坐标 (x, y)、一份固定配置、数据库读出来的一行记录。用元组包起来,等于给数据上一道"完整性约束"------谁改谁报错,解释器帮你盯着。另外,元组因为不可变,可以当作字典的键,列表不行。

创建与陷阱

python 复制代码
# data_structures/tuple_demo.py
zoo = ('tiger', 'lion', 'zebra')   # 括号可省,但建议保留,语义更清楚
empty = ()                         # 空元组
single = ('deer',)                 # 单元素元组:逗号不能省!

# 下面这行不是元组,而是带括号的字符串 'deer'
not_a_tuple = ('deer')

print(zoo[2])                      # 'zebra',索引访问和列表一样
for animal in zoo:
    print(animal)

single = ('deer',) 这个逗号是最容易写错的地方 :少了逗号,Python 只当它是普通括号表达式,type(single) 会是 str 而不是 tuple

小结 :元组 = 不可变列表。需要"定值"或要当字典键时用它;单元素别忘了加尾逗号 ('x',)


四、字典 dict:键值对的查找表

为什么用它

如果用列表存"名字→电话",查一个人得从头遍历,慢。字典按直接定位值,查找接近 O(1)------本质是哈希表。所有"通过某个标识取对应信息"的场景(联系人、配置、缓存、JSON)都该用字典。

创建与增删改查

python 复制代码
# data_structures/dict_demo.py
contact = {'z3': '119', 'l4': '110', 'w5': '114'}

# 增 / 改:键存在就覆盖,不存在就新增
contact['l7'] = '120'
contact['l7'] = '111'

# 查:直接索引键不存在会抛 KeyError,优先用 get
print(contact['l4'])                 # '110'
print(contact.get('l4'))             # '110'
print(contact.get('lao8', 'not exists'))  # 键不存在返回默认值,不报错

# 删
contact.pop('l7')                     # 返回被删的值
# del contact['l7']                  # 等价,但不返回值

# 迭代:键值对 / 只键 / 只值
for k, v in contact.items():
    print(k, v)
for k in contact.keys():
    print(k)
for v in contact.values():
    print(v)

要点:

  • 键必须不可变且唯一 :键可以是 str/int/tuple 等可哈希对象,不能是 list;重复键后者覆盖前者。
  • 排序:字典本身无序,要按 key 排序只能 for k in sorted(contact): print(k, contact[k])
  • 值没有限制,可以是列表、字典甚至函数。

小结 :字典是"用名字查东西"的标准结构。键要不可变、取值优先 getKeyError,这是字典的两大铁律。


五、序列:list / tuple / str 的共同语言

为什么单独讲"序列"

列表、元组、字符串看上去不一样,但都遵守同一套"序列协议":能索引、能切片、能测成员、能拼接、能求长度。理解"序列"这个抽象,这三种类型不用分别背------学会一个,三个都会

python 复制代码
# data_structures/sequence_demo.py
zoo = ('tiger', 'lion', 'zebra', 'elephant', 'fox', 'wolf', 'puma')

# 1. 资格测试
'tiger' in zoo          # True
'lion' not in zoo       # False

# 2. 索引(负索引从末尾算)
zoo[3]                  # 'elephant'
zoo[-1]                 # 'puma'

# 3. 切片 [start:end:step],左闭右开
zoo[2:5]                # ('zebra', 'elephant', 'fox')
zoo[2:]                 # 从 2 到结尾
zoo[:5]                 # 从 0 到 5
zoo[2:-1]               # 去掉头尾
zoo[-3:-5:-1]           # 负步长反向切:('wolf', 'fox')
zoo[2:5:2]              # 每隔一个取:('zebra', 'fox')

# 4. 拼接与重复(都返回新对象,原序列不变)
zoo + ('cat', 'dog')    # 拼接
zoo * 2                 # 重复
len(zoo)                # 7

字符串同样是序列,上面所有操作照用:'abcdefg'[2:-1:2]'hi' * 3'c' in 'abc'

小结 :序列是 list/tuple/str 的共同抽象。切片 [start:end:step] 左闭右开、可负;+ 拼接、* 重复都返回新对象,不动原数据。


六、集合 set:去重与集合运算

为什么用它

要"去掉重复元素"或做"哪些人既在 A 组又在 B 组"这类关系运算,用列表得手写循环,又慢又丑。集合天生无序、元素唯一,专为去重数学集合运算 设计;而且 in 成员测试是 O(1),比列表的 O(n) 快得多。

python 复制代码
# data_structures/set_demo.py
bri = set(['brazil', 'russia', 'india'])
bric = bri.copy()           # 复制一份,避免改到原集合
bric.add('China')           # 添加元素

# 集合运算
bric & bri                  # 交集:两集合共有
bric | bri                  # 并集:全部合起来
bric - bri                  # 差集:bric 有而 bri 没有
bric.issuperset(bri)        # bric 是否包含 bri 的全部

# 资格测试(比 list 快)
'China' in bric             # True

bric.remove('india')        # 元素必须存在,否则抛 KeyError
bric.discard('india')       # 不存在也不报错,更稳妥
bric.clear()

要点:集合元素必须可哈希(不可变) ,所以 set([1, 2, 3]) 行,set([[1, 2], [3, 4]]) 报错(列表不可哈希)。去重最常用的一招:unique = list(set(some_list))

小结 :集合管"去重 + 关系运算"。& 交、| 并、- 差、in 测试 O(1);元素必须可哈希,删元素用 discardremove 安全。


七、引用陷阱:= 是"贴标签"不是"复制"

为什么这是个坑

Python 的变量不是"盒子",而是贴在数据对象上的标签 。写 b = a 时,a 和 b 指向同一块内存。对不可变对象(数字、字符串)无所谓,反正改不了;但对列表、字典这类可变容器,通过一个名字改了,另一个名字看到的全跟着变------这种"幽灵联动"是新手 bug 的重灾区。

python 复制代码
# data_structures/reference_demo.py
original = ['apple', 'banana', 'pear']
alias = original            # alias 和 original 指向同一个列表对象

del original[0]
print(alias)                # ['banana', 'pear'] ------ 跟着变了!

# 正确复制:切片创建独立副本
copy = original[:]
# 或 copy = original.copy() / copy = list(original)
del original[0]
print(copy)                 # ['banana', 'pear'] ------ 不受影响

复制可变对象的几种正确姿势:

  • 列表:new = old[:]new = old.copy()
  • 字典:new = old.copy()
  • 通用深拷贝:import copy; new = copy.deepcopy(old)(对象里还套对象时用)

小结= 是绑定不是复制。可变对象要独立副本,用切片 [:].copy();嵌套结构用 copy.deepcopy


数据结构本身不难,难在看到需求时选对结构:要顺序和改动就用 list,要定值就用 tuple,要按名查就用 dict,要去重算关系就用 set。把这四个选对了,代码自然又短又清楚------后面写 FastAPI 的入参校验、响应模型、缓存,全都是这四种结构在干活。

相关推荐
冻柠檬飞冰走茶1 小时前
PTA基础编程题目集 7-27 冒泡法排序(C语言实现)
c语言·开发语言·数据结构·算法
听雨入夜1 小时前
“同声传译”还是“全文翻译”?为何HotSpot虚拟机仍要保留解释器?
开发语言·python
随风M记忆s2 小时前
GEE&Python-demo:利用Sentinel-监测北京奥林匹克森林公园年NDVI变化(附Python版)
开发语言·python·sentinel
软萌萌的12 小时前
Python零基础从入门到精通详细教程-数据类型
开发语言·windows·python
东北赵四2 小时前
关于Java泛型的知识点及其相关面试题
java·windows·python
姓蔡小朋友2 小时前
Java线程并发
java·开发语言·python
海带紫菜菠萝汤2 小时前
免费在线翻译器横评:2026年6款PDF翻译工具对比
人工智能·python·pdf
编程阿峰3 小时前
Python 环境配置(二)安装jupyter、matplotlib、numpy库
开发语言·python·jupyter·numpy·matplotlib
AC赳赳老秦3 小时前
CSDN 技术社区数据采集:OpenClaw 抓取公开技术热帖,生成领域技术热点周报
java·大数据·前端·数据库·python·php·openclaw