Python 3 字典(dict)、集合(set)、元组(tuple)

📅 2026/7/2 2:35:26
Python 3 字典(dict)、集合(set)、元组(tuple)
一、元组tuple—— 不可变的序列1.1 创建元组元组用圆括号()表示一旦创建就不能修改。# 直接创建 point (3, 4) rgb (255, 128, 0) # 单元素元组必须加逗号这是最常见的坑 single (42,) # 这是一个元组 not_tuple (42) # 这只是一个整数 42 # 省略括号也可以 coords 3, 4 # 等价于 (3, 4) # 从其他可迭代对象转换 t tuple([1, 2, 3]) # (1, 2, 3) t tuple(hello) # (h, e, l, l, o) t tuple(range(5)) # (0, 1, 2, 3, 4) # 空元组 empty ()1.2 基本操作colors (red, green, blue, green) # 索引访问从 0 开始 colors[0] # red colors[-1] # blue最后一个元素 # 切片 colors[1:3] # (green, blue) # 拼接生成新元组原元组不变 colors (yellow,) # (red, green, blue, green, yellow) # 重复 (ha,) * 3 # (ha, ha, ha) # 成员判断 red in colors # True # 长度 len(colors) # 4 # 计数和查找索引 colors.count(green) # 2 colors.index(blue) # 21.3 解包unpacking这是元组最常用也最优雅的特性之一# 基本解包 point (3, 4) x, y point print(x, y) # 3 4 # 交换变量不需要临时变量 a, b 10, 20 a, b b, a print(a, b) # 20 10 # 用 * 收集多余元素 first, *rest (1, 2, 3, 4, 5) print(first) # 1 print(rest) # [2, 3, 4, 5] head, *middle, tail (1, 2, 3, 4, 5) print(head) # 1 print(middle) # [2, 3, 4] print(tail) # 5 # 忽略某些值 _, y, _ (1, 2, 3) # 只关心 y1.4 为什么用元组数据不可变可以作为字典的键、集合的元素列表不行语义明确表示这组数据是一个整体不应该被修改比如坐标(x, y)、RGB 颜色值比列表性能略好因为不可变Python 可以做内部优化# 元组可以做字典的键 location {} location[(35.68, 139.69)] Tokyo location[(40.71, -74.01)] New York # 列表不行会报 TypeError # location[[35.68, 139.69]] Tokyo # TypeError!二、字典dict—— 键值对映射2.1 创建字典# 花括号直接创建 person {name: Alice, age: 30, city: Beijing} # dict() 构造函数 config dict(hostlocalhost, port8080, debugTrue) # 从键值对列表创建 items [(a, 1), (b, 2), (c, 3)] d dict(items) # {a: 1, b: 2, c: 3} # 用 dict.fromkeys() 创建默认值字典 keys [name, age, email] profile dict.fromkeys(keys, unknown) # {name: unknown, age: unknown, email: unknown} # 空字典 empty {}2.2 增删改查student {name: Bob, age: 20} # ---- 读取 ---- student[name] # Bob student.get(gpa) # None键不存在返回 None student.get(gpa, 0.0) # 0.0键不存在返回默认值 student.get(name, N/A) # Bob键存在返回实际值 # ---- 添加 / 修改 ---- student[gpa] 3.8 # 键不存在添加 student[age] 21 # 键已存在修改 # ---- 删除 ---- del student[gpa] # 删除指定键 age student.pop(age) # 删除并返回值age 被赋值为 21 # ---- 批量更新 ---- student.update({major: CS, year: 3}) student.update(cityShanghai) # 也可以用关键字参数2.3 遍历字典scores {math: 95, english: 88, physics: 92} # 遍历键 for subject in scores: print(subject) for subject in scores.keys(): print(subject) # 遍历值 for score in scores.values(): print(score) # 遍历键值对最常用 for subject, score in scores.items(): print(f{subject}: {score})2.4 常用方法d {a: 1, b: 2, c: 3} len(d) # 3键值对数量 a in d # True检查键是否存在 1 in d # Falsein 检查的是键不是值 d.copy() # 浅拷贝 d.setdefault(d, 0) # 如果键不存在就设置默认值并返回存在则返回已有值 list(d.keys()) # [a, b, c] list(d.values()) # [1, 2, 3] list(d.items()) # [(a, 1), (b, 2), (c, 3)] # popitem()移除并返回最后插入的键值对 d.popitem() # (c, 3)2.5 实际应用示例统计词频text apple banana apple cherry banana apple word_count {} for word in text.split(): word_count[word] word_count.get(word, 0) 1 # {apple: 3, banana: 2, cherry: 1}用 collections.Counter 更简洁地实现from collections import Counter text apple banana apple cherry banana apple word_count Counter(text.split()) # Counter({apple: 3, banana: 2, cherry: 1})分组数据students [ {name: Alice, grade: A}, {name: Bob, grade: B}, {name: Charlie, grade: A}, {name: Diana, grade: B}, ] groups {} for s in students: grade s[grade] groups.setdefault(grade, []).append(s[name]) # {A: [Alice, Charlie], B: [Bob, Diana]}多条件查找嵌套字典users { alice: {age: 30, role: admin}, bob: {age: 25, role: user}, carol: {age: 28, role: admin}, } # 找出所有管理员 admins [name for name, info in users.items() if info[role] admin] # [alice, carol]三、集合set—— 无序、不重复的元素集3.1 创建集合# 花括号创建注意空集合只能用 set() fruits {apple, banana, cherry} # set() 从其他可迭代对象创建 nums set([1, 2, 3, 2, 1]) # {1, 2, 3}自动去重 chars set(hello) # {h, e, l, o}去重 无序 # 空集合不能用 {}那是空字典 empty set() # 集合推导式 squares {x ** 2 for x in range(5)} # {0, 1, 4, 9, 16}3.2 基本操作s {1, 2, 3} # 添加元素 s.add(4) # {1, 2, 3, 4} s.add(3) # {1, 2, 3, 4}已存在无变化 # 删除元素 s.remove(2) # 不存在会抛出 KeyError s.discard(99) # 不存在也不报错推荐用这个 popped s.pop() # 移除并返回一个任意元素无序的 # 清空 s.clear() # set() # 成员判断O(1) 时间复杂度非常快 3 in {1, 2, 3} # True3.3 集合运算这是集合最强大的特性可以直接用运算符做数学上的集合操作a {1, 2, 3, 4} b {3, 4, 5, 6} # 并集两个集合的所有元素 a | b # {1, 2, 3, 4, 5, 6} a.union(b) # 同上 # 交集两个集合的共同元素 a b # {3, 4} a.intersection(b) # 差集在 a 中但不在 b 中 a - b # {1, 2} a.difference(b) # 对称差集在 a 或 b 中但不同时在两者中 a ^ b # {1, 2, 5, 6} a.symmetric_difference(b) # 子集 / 超集判断 {1, 2} {1, 2, 3} # True子集 {1, 2, 3} {1, 2} # True超集 {1, 2} {1, 2, 3} # True真子集 {1, 2, 3}.issubset({1, 2, 3, 4}) # True # 判断是否无交集 {1, 2}.isdisjoint({3, 4}) # True3.4 原地集合运算a {1, 2, 3} b {2, 3, 4} a | {5, 6} # a 变成 {1, 2, 3, 5, 6}并集后更新自身 a b # a 变成 {2, 3}交集后更新自身 a - {2} # a 变成 {3}差集后更新自身3.5 实际应用示例列表去重data [3, 1, 4, 1, 5, 9, 2, 6, 5, 3] unique list(set(data)) # [1, 2, 3, 4, 5, 6, 9]顺序不保证 unique_ordered list(dict.fromkeys(data)) # [3, 1, 4, 5, 9, 2, 6]保序去重快速判断元素是否在集合中# 用列表O(n) 慢 valid_ids [1001, 1002, 1003, ...] if user_id in valid_ids: # 每次都要遍历整个列表 pass # 用集合O(1) 快 valid_ids {1001, 1002, 1003, ...} if user_id in valid_ids: # 瞬间判断 pass找出两个数据源的差异yesterday {alice, bob, carol} today {bob, carol, diana} new_users today - yesterday # {diana} 新增的用户 left_users yesterday - today # {alice} 离开的用户 stayed yesterday today # {bob, carol} 留下的用户四、frozenset —— 不可变的集合frozenset是集合的不可变版本创建后不能添加或删除元素。因为不可变所以可以作为字典的键或集合的元素fs frozenset([1, 2, 3]) # 不能修改 # fs.add(4) # AttributeError! # 可以做字典的键 graph { frozenset({A, B}): 1.5, frozenset({B, C}): 2.3, }五、三者对比特性元组 tuple字典 dict集合 set语法(1, 2, 3){a: 1}{1, 2, 3}可变性不可变可变可变是否有序有序按位置有序Python 3.7 保持插入顺序无序是否允许重复允许键不允许重复不允许主要用途固定的数据组合键值映射 / 查找去重 / 集合运算 / 快速判断成员可做字典的键可以不可以不可以frozenset 可以空值写法(){}set()六、何时用哪个用元组当你需要表示一个固定结构的数据坐标、颜色、数据库记录行作为字典的键函数返回多个值用字典当你需要通过名字键快速查找值表示一个实体的多个属性做缓存 / 计数 / 分组用集合当你需要去重判断某个元素是否在一组数据中并且要快做交集、并集、差集等运算七、常见陷阱1. 用{}创建的不是空集合type({}) # class dict不是 set type(set()) # class set2. 集合和字典的键必须是可哈希类型# 可以int、float、str、tuple元素也必须可哈希、bool、None # 不可以list、dict、set bad_set {[1, 2]} # TypeError: unhashable type: list bad_dict {[1, 2]: 3} # TypeError: unhashable type: list3. 元组虽不可变但如果元素是可变对象那个元素本身仍可变t (1, [2, 3], 4) t[1].append(99) print(t) # (1, [2, 3, 99], 4) # t[1] [5, 6] # 这才是 TypeError不能替换元素本身4. 字典的浅拷贝不会复制嵌套对象original {names: [Alice, Bob]} copy original.copy() copy[names].append(Charlie) print(original) # {names: [Alice, Bob, Charlie]} ← 也被改了 # 需要深拷贝时 import copy deep copy.deepcopy(original)