Python 集合
set/frozenset 提供去重与集合运算;元素须可哈希,frozenset 可作字典键。
#type / concept
#status / growing
#tech / dev
#resource / python
#tech / lang / python
[!info] 关联笔记
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 仅便展示)。
- 黑名单用 set,成员测试比 list 扫描稳。
- frozenset 忽略构造顺序,相同元素即同一键。
核心概念与准确模型
| 运算 | 语法/方法 |
|---|---|
| 并 | | / union |
| 交 | & / intersection |
| 差 | - / difference |
| 对称差 | ^ / symmetric_difference |
| 子集 | <= / < |
- 字面量:
{1,2};空集必须set()({}是空 dict) - 推导:
{x for x in xs if cond}
边界情况与反直觉行为
- list 不能进 set;改用 tuple。
- 浮点 NaN 哈希/相等行为特殊,慎作元素。
- 修改正在迭代的 set 会运行时错误。
常见误区
[!warning] 常见误区:
{}创建空 set 错误理解:与空 dict 同形。
正确模型:空 set 写set()。
工程实践
- 权限、标签、去重 ID 优先 set。
- 需要稳定顺序 + 去重:
dict.fromkeys(xs)或有序结构。 - 对外 API 可用 frozenset 防止调用方 add/remove。
本节总结
集合解决去重、成员与集合代数。选 set/frozenset 的关键是元素可哈希与是否需要不可变键。
自测题
- 为什么
frozenset({"vip","spring"})能命中以另一顺序构造的键? - 空集字面量怎么写?
参考答案
- frozenset 相等只看元素集合,与插入顺序无关。
set()。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| Set Types | 文档 | set API |