Python 集合
set/frozenset 提供去重与集合运算;元素须可哈希,frozenset 可作字典键。
#concept
#growing
#dev
#python
#python
[!info] related notes
Python 集合
这个概念为什么出现
权限差集、标签去重、已处理 ID 集合——这些是集合问题,不是“再写一层 for”。set 提供平均 O(1) 成员测试与并交差运算;frozenset 给出不可变、可哈希版本。
[!abstract] 一句话理解
set是可变无序不重复元素集合;frozenset不可变且可哈希;元素必须可哈希。
最小可运行示例
先把示例放进业务场景,再看代码:
场景:优惠券系统计算可领券用户
营销要:新客集合与黑名单差集,得到可发券用户;活动标签集合要能当缓存键。
# coupon_sets.py
# 业务意图:用集合运算过滤可发券用户,并用 frozenset 作缓存键。
# 教学点:
# - set 去重与差集;
# - 成员测试;
# - frozenset 可作 dict 键。
def eligible_users(new_users: list[str], blocked: set[str]) -> set[str]:
return set(new_users) - blocked
def main() -> None:
blocked = {"u:spam", "u:risk"}
can_receive = eligible_users(["u:1", "u:2", "u:1", "u:spam"], blocked)
print("eligible:", sorted(can_receive))
print("u:2 in eligible?", "u:2" in can_receive)
tags = frozenset({"vip", "spring"})
campaign_cache = {tags: "10OFF"}
print("cache:", campaign_cache[frozenset({"spring", "vip"})])
if __name__ == "__main__":
main()
建议运行:
python coupon_sets.py
期望输出:
eligible: ['u:1', 'u:2']
u:2 in eligible? True
cache: 10OFF
结合场景再看三个关注点
- 去重是集合语义,不是排序;输出顺序不保证(示例用 sorted 仅便展示)。
- 哈希集合通常提供平均 O(1) 成员测试,仍受哈希/相等比较成本及碰撞影响;不是每次都比小 list 更快。
- frozenset 忽略构造顺序,相同元素即同一键。
核心概念与准确模型
| 运算 | 语法/方法 |
|---|---|
| 并 | | / union |
| 交 | & / intersection |
| 差 | - / difference |
| 对称差 | ^ / symmetric_difference |
| 子集 | <= / < |
- 字面量:
{1,2};空集必须set()({}是空 dict) - 推导:
{x for x in xs if cond} - union/intersection 等方法可接收一般 iterable;|、& 等运算符要求集合类操作数。
边界情况与反直觉行为
- list 不可哈希,不能作 set 元素;转成 tuple 后还须所有元素可哈希。True、1、1.0 相等,放进集合会合并。
- 不同 NaN 对象彼此不相等,set 不保证把所有 NaN 合成一个;按业务去重需先定义缺失/NaN 的规范化策略。
- 遍历时不要增删集合元素;改变大小通常抛 RuntimeError,但不能依赖异常检测所有逻辑错误。
常见误区
[!warning] 常见误区:
{}创建空 set 错误理解:与空 dict 同形。
正确模型:空 set 写set()。
工程实践
- 权限、标签、去重 ID 优先 set。
- 需要稳定顺序 + 去重:
dict.fromkeys(xs)或有序结构。 - frozenset 禁止增删元素,但不会冻结自定义元素的内部状态;元素仍须遵守稳定的哈希/相等契约。
本节总结
集合解决去重、成员与集合代数。选 set/frozenset 的关键是元素可哈希与是否需要不可变键。
自测题
- 为什么
frozenset({"vip","spring"})能命中以另一顺序构造的键? - 空集字面量怎么写?
参考答案
- frozenset 相等只看元素集合,与插入顺序无关。
set()。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| Set Types | 文档 | set API |