ZetCode

Python frozenset 函数

上次修改时间:2025 年 4 月 11 日

本综合指南探讨了 Python 的 frozenset 函数,该函数创建不可变的集合对象。我们将介绍创建、操作、用例以及使用不可变集合的实际示例。

基本定义

frozenset 函数返回一个不可变的集合对象。与常规集合不同,frozenset 在创建后无法修改。它们是可哈希的,可以用作字典键。

关键特性:不可变,无序,唯一元素,支持集合操作(并集、交集等),并且可哈希。元素必须是可哈希的。

创建 Frozenset

以下是基本用法,展示了如何从不同的可迭代对象创建 frozenset。这些示例演示了如何从列表、字符串和其他集合创建。

basic_frozenset.py
# From a list
numbers = frozenset([1, 2, 3, 2, 1])
print(numbers)  # frozenset({1, 2, 3})

# From a string
letters = frozenset("hello")
print(letters)  # frozenset({'h', 'e', 'l', 'o'})

# From another set
regular_set = {4, 5, 6}
frozen = frozenset(regular_set)
print(frozen)   # frozenset({4, 5, 6})

此示例展示了创建 frozenset 的三种方法。重复项会自动删除,就像常规集合一样。元素的顺序不会保留。

请注意,虽然 frozenset 本身是不可变的,但其元素也必须是不可变的(可哈希的)类型。

使用 Frozenset 作为字典键

此示例演示了如何将 frozenset 用作字典键,这对于常规可变集合是不可能的。

frozenset_keys.py
# Create a dictionary with frozenset keys
config = {
    frozenset(['admin', 'user']): "Full access",
    frozenset(['user']): "Read-only access",
    frozenset(['guest']): "No access"
}

# Access values using frozenset keys
print(config[frozenset(['user'])])        # Read-only access
print(config[frozenset(['admin', 'user'])]) # Full access

# Trying with regular set would raise TypeError
try:
    {set(['a']): "value"}
except TypeError as e:
    print(f"Error: {e}")  # unhashable type: 'set'

这展示了 frozenset 如何在字典中启用类似集合的键。该示例将权限集映射到访问级别。常规集合不能用作键。

该错误演示了为什么需要 frozenset 来处理此用例 - 常规集合是可变的,因此不可哈希。

Frozenset 的集合操作

Frozenset 支持所有标准集合操作。此示例演示了并集、交集、差集和对称差集操作。

set_operations.py
fs1 = frozenset([1, 2, 3, 4])
fs2 = frozenset([3, 4, 5, 6])

# Union
print(fs1 | fs2)   # frozenset({1, 2, 3, 4, 5, 6})

# Intersection
print(fs1 & fs2)   # frozenset({3, 4})

# Difference
print(fs1 - fs2)   # frozenset({1, 2})

# Symmetric difference
print(fs1 ^ fs2)   # frozenset({1, 2, 5, 6})

# These operations return new frozensets
result = fs1 | fs2
print(type(result))  # <class 'frozenset'>

所有标准集合操作都适用于 frozenset 并返回新的 frozenset。由于 frozenset 是不可变的,因此这些操作不会修改原始 frozenset。

请注意,您可以在这些操作中将 frozenset 与常规集合混合使用,但结果类型取决于左侧操作数。

成员资格测试和方法

此示例显示了成员资格测试和可用的 frozenset 方法。虽然 frozenset 是不可变的,但它们支持所有非突变集合方法。

methods.py
colors = frozenset(['red', 'green', 'blue'])

# Membership testing
print('red' in colors)    # True
print('yellow' in colors) # False

# Non-mutating methods
print(colors.isdisjoint(frozenset(['yellow'])))  # True
print(colors.issubset({'red', 'green', 'blue', 'yellow'}))  # True
print(colors.issuperset({'red', 'green'}))      # True

# len(), copy() work as expected
print(len(colors))        # 3
colors_copy = colors.copy()
print(colors_copy)        # frozenset({'red', 'green', 'blue'})

Frozenset 支持所有不修改集合的集合操作。成员资格测试非常高效(O(1)),就像常规集合一样。

诸如 isdisjointissubsetissuperset 之类的方法对于集合比较特别有用。

数据结构中的 Frozenset

此高级示例演示了如何在更复杂的数据结构中使用 frozenset,从而利用其可哈希性和不变性。

data_structures.py
from collections import defaultdict

# Using frozenset in a defaultdict
graph = defaultdict(set)

# Add edges (undirected graph)
edges = [
    frozenset({'A', 'B'}),
    frozenset({'B', 'C'}),
    frozenset({'C', 'A'}),
    frozenset({'C', 'D'})
]

for edge in edges:
    for node in edge:
        graph[node].update(edge - {node})

print(graph)
# defaultdict(<class 'set'>, {
#   'A': {'B', 'C'}, 
#   'B': {'A', 'C'}, 
#   'C': {'A', 'B', 'D'}, 
#   'D': {'C'}
# })

# Using frozenset in a set of sets
unique_combinations = {
    frozenset({'a', 'b'}),
    frozenset({'b', 'c'}),
    frozenset({'a', 'c'})
}

print(frozenset({'b', 'a'}) in unique_combinations)  # True

这展示了两个高级用例:图边存储和唯一组合。Frozenset 确保边缘表示与顺序无关且可哈希。

图示例有效地存储了每个节点的邻居。组合示例演示了 frozenset 如何表示无序对。

最佳实践

资料来源

作者

我叫 Jan Bodnar,是一位充满热情的程序员,拥有丰富的编程经验。自 2007 年以来,我一直在撰写编程文章。到目前为止,我已经撰写了 1,400 多篇文章和 8 本电子书。我拥有超过十年的编程教学经验。

列出所有 Python 教程