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

结合场景再看三个关注点

  1. 去重是集合语义,不是排序;输出顺序不保证(示例用 sorted 仅便展示)。
  2. 黑名单用 set,成员测试比 list 扫描稳。
  3. frozenset 忽略构造顺序,相同元素即同一键。

核心概念与准确模型

运算语法/方法
| / union
& / intersection
- / difference
对称差^ / symmetric_difference
子集<= / <
  • 字面量:{1,2};空集必须 set(){} 是空 dict)
  • 推导:{x for x in xs if cond}

边界情况与反直觉行为

  1. list 不能进 set;改用 tuple。
  2. 浮点 NaN 哈希/相等行为特殊,慎作元素。
  3. 修改正在迭代的 set 会运行时错误。

常见误区

[!warning] 常见误区:{} 创建空 set 错误理解:与空 dict 同形。
正确模型:空 set 写 set()

工程实践

  • 权限、标签、去重 ID 优先 set。
  • 需要稳定顺序 + 去重:dict.fromkeys(xs) 或有序结构。
  • 对外 API 可用 frozenset 防止调用方 add/remove。

本节总结

集合解决去重、成员与集合代数。选 set/frozenset 的关键是元素可哈希与是否需要不可变键。

自测题

  1. 为什么 frozenset({"vip","spring"}) 能命中以另一顺序构造的键?
  2. 空集字面量怎么写?
参考答案
  1. frozenset 相等只看元素集合,与插入顺序无关。
  2. set()

延伸阅读与资料来源

资料类型支撑内容
Set Types文档set API
创建于 2026/7/15 更新于 2026/7/15