当前位置:首页>python>Python3入门系列 | Day 6: 元组与集合——那些不可变和去重

Python3入门系列 | Day 6: 元组与集合——那些不可变和去重

  • 2026-10-11 08:11:46
Python3入门系列 | Day 6: 元组与集合——那些不可变和去重
上篇讲了列表和字典,你已经知道怎么存一堆东西了。但 Python 里还有两种数据结构,出场率也很高——元组(tuple) 和 集合(set)。

简单说:

  • 元组 = 不能改的列表,适合存"定下来就不变"的数据
  • 集合 = 自动去重的无序集合,适合做数学上的集合运算

一、元组(tuple)——锁定它,别改

长什么样?

# 用圆括号,元素用逗号隔开t1 = (1, 2, 3)t2 = ("苹果", "香蕉", "橘子")t3 = (1, "hello", 3.14)  # 可以混装不同类型

元组能干啥?

1. 元组跟列表一样,可以索引、切片、遍历

t = ("北京", "上海", "广州", "深圳")print(t[0])      # 北京print(t[1:3])    # ('上海', '广州')for city in t:print(city)

2. 但!不能修改元素

t = (1, 2, 3)t[0] = 100# 报错!TypeError: 'tuple' object does not support item assignment

这是元组和列表最大的区别。所以叫「不可变序列」。

什么时候用元组而不是列表?

函数的多个返回值——这个超常用

defget_user():    name = "张三"    age = 28return name, age  # 返回的其实就是元组user = get_user()print(user)      # ('张三', 28)print(user[0])   # 张三

字典的键——列表不行,但元组可以(原因见下文)

# 用坐标做键locations = {    (39.9, 116.4): "北京",    (31.2, 121.4): "上海"}print(locations[(39.9, 116.4)])  # 北京

数据不该被意外修改——比如配置常量

# 一周七天,写死了别动WEEKDAYS = ("周一", "周二", "周三", "周四", "周五", "周六", "周日")

一个坑:单元素元组

not_tuple = (1)       # 这是整数1,不是元组!is_tuple = (1,)       # 加个逗号,这才是元组

第一天踩过的坑,现在还债。单元素元组一定要加逗号。


补充知识:为什么有些类型可以做字典的键,有些不行?

哪些可以,哪些不行?

可作为字典键
不可作为字典键
字符串 str
列表 list
整数 int
字典 dict
浮点数 float
集合 set
布尔值 bool
元组 tuple(如果内含可变对象则不行)
冻结集合 frozenset

原因:字典键必须"可哈希"

Python 字典底层是哈希表。存一个键值对时,Python 会计算键的哈希值来确定存放位置。

hash("hello")     # 产生一个固定整数hash(42)          # 产生一个固定整数hash((1, 2, 3))   # 产生一个固定整数hash([1, 2, 3])   # 报错!unhashable type: 'list'

不可变类型(字符串、数字、元组)的哈希值在整个生命周期中固定不变,所以能做键。

可变类型(列表、字典)的内容可以随时改,改了哈希值就变了,之前存的数据就找不到了——所以 Python 禁止它们当键。

d = {}d[[1, 2]] = "value"# 报错!列表不可哈希d[(1, 2)] = "value"# 正常工作

但元组里装了可变对象也不行:

hash((1, [2, 3]))  # 报错!元组内含列表,整体不可哈希

二、集合(set)——去重小能手

长什么样?

# 用花括号,元素逗号隔开s1 = {1, 2, 3, 4, 5}s2 = {"a", "b", "c"}

注意——空集合不能用 {},那是空字典。

empty_set = set()      # 空集合empty_dict = {}        # 这是空字典

集合三大特性

特性
含义
例子
无序
元素没有顺序,不能通过索引取值
{3, 1, 2}
 打印可能是 {1, 2, 3}
唯一
重复元素自动合并,只留一个
{1, 2, 2, 3}
 → {1, 2, 3}
可哈希
元素本身不能是可变类型
{[1,2]}
 报错

集合最常用的两个操作

1. 去重

names = ["张三", "李四", "张三", "王五", "李四"]unique_names = set(names)print(unique_names)  # {'张三', '李四', '王五'}

再转回列表也很简单:

names_list = list(set(names))

2. 集合运算

a = {1, 2, 3, 4, 5}b = {4, 5, 6, 7, 8}# 交集——两边都有的print(a & b)   # {4, 5}print(a.intersection(b))  # {4, 5}# 并集——合并去重print(a | b)   # {1, 2, 3, 4, 5, 6, 7, 8}# 差集——a有b没有的print(a - b)   # {1, 2, 3}print(b - a)   # {8, 6, 7}# 对称差集——去掉交集剩下的print(a ^ b)   # {1, 2, 3, 6, 7, 8}

真实场景:两个群成员分析

group_a = {"张三", "李四", "王五", "赵六"}group_b = {"李四", "赵六", "钱七", "孙八"}# 同时在两个群的人common = group_a & group_bprint(f"同时在两个群: {common}")# 只在A群的人only_a = group_a - group_bprint(f"只在A群: {only_a}")# 合并所有成员(去重)all_members = group_a | group_bprint(f"总成员数: {len(all_members)}")

遍历集合

s = {"Python", "Java", "Go", "Rust"}for lang in s:print(lang)# 注意:顺序不确定!每次运行顺序可能不一样

补充知识:什么类型能做集合的元素?

集合的元素要求和字典键一样——必须是可哈希的不可变类型。

可作为集合元素
不可作为集合元素
整数 int
列表 list
浮点数 float
字典 dict
字符串 str
集合本身 set
元组 tuple
frozenset
{1, 2, 3}                   # 正常{"a", "b"}                  # 正常{(1, 2), (3, 4)}            # 正常(元组不可变){[1, 2], [3, 4]}            # 报错!列表不可哈希{{1, 2}}                    # 报错!集合本身可变

如果你想装一个"不可变的集合",用 frozenset:

fs = frozenset([1, 2, 3])   # 不可变集合,可以放进集合里{frozenset([1, 2]), frozenset([3, 4])}  # 正常

补充知识:元组里的可变元素

元组的直接元素不能改,但如果元素本身是可变对象——那它内部可以变。

t = ([1, 2], 3)t[0].append(100)  # 可以!元组没变,是列表变了print(t)  # ([1, 2, 100], 3)

元组存的是引用,不是值。


今日小结

  • 元组:用 (),不能改,适合存固定数据、做函数返回值、当字典键
  • 集合:用 {} 或 set(),自动去重,支持交集、并集、差集运算
  • 字典键和集合元素都要求"可哈希"——不可变类型(字符串、数字、元组)可以,可变类型(列表、字典、集合)不行,底层原因是哈希表需要键的哈希值固定不变
  • 空元组是 (),空集合是 set(),空字典是 {}

一句话记法:数据写死了不想改→用元组;数据要去重或算交集差集→用集合。

明天讲字符串操作,文本处理基本功,是写代码几乎每天都要用的东西。

最新文章

随机文章