杰瑞科技汇

python frozensets

Of course! Let's dive deep into Python's frozenset.

python frozensets-图1
(图片来源网络,侵删)

What is a frozenset?

A frozenset is a Python built-in data type that is an immutable version of the standard set.

Think of it like this:

  • A set is like a box of building blocks. You can add new blocks, remove blocks, or swap blocks around. It's mutable (changeable).
  • A frozenset is like a perfectly cast statue made from those blocks. Once it's made, you can't change it in any way. It's immutable (unchangeable).

The Key Difference: set vs. frozenset

Feature set frozenset
Mutability Mutable (can be changed after creation) Immutable (cannot be changed after creation)
Methods to Modify .add(), .remove(), .discard(), .pop(), .update(), etc. None. No methods to add or remove elements.
Hashable No. Cannot be used as a key in a dictionary or as an element in another set. Yes. Can be used as a key in a dictionary or as an element in another set.
Syntax my_set = {1, 2, 3} my_frozenset = frozenset([1, 2, 3])

Why Use frozenset? (The Main Use Cases)

The immutability of frozenset might seem like a limitation, but it's precisely what makes it useful in specific situations.

As Dictionary Keys

Since dictionary keys must be hashable and immutable, you can't use a regular set as a key. A frozenset is perfect for this.

python frozensets-图2
(图片来源网络,侵删)

Imagine you want to create a dictionary where the keys are sets of coordinates.

# This will NOT work!
# regular_set = {(10, 20), (30, 40)}
# location_data = {regular_set: "Home"} # TypeError: unhashable type: 'set'
# This WILL work!
frozen_location = frozenset([(10, 20), (30, 40)])
location_data = {frozen_location: "Home"}
print(location_data)
# Output: {frozenset({(10, 20), (30, 40)}): 'Home'}
# You can now access the value using the same frozenset
print(location_data[frozen_location])
# Output: 'Home'

As Elements in Other Sets

A set can only contain hashable (immutable) elements. Since a set is mutable, you can't have a set of sets. But you can have a set of frozensets.

# This will NOT work!
# set_of_sets = {{1, 2}, {3, 4}} # TypeError: unhashable type: 'set'
# This WILL work!
frozen_set1 = frozenset([1, 2])
frozen_set2 = frozenset([3, 4])
set_of_frozensets = {frozen_set1, frozen_set2}
print(set_of_frozensets)
# Output: {frozenset({1, 2}), frozenset({3, 4})}

When You Need a "Constant" Set

Sometimes you want to define a collection of unique items that should never be modified by accident. Using a frozenset signals to other developers (and to yourself) that this collection is fixed and should not be altered.

# A set of valid user roles that should never change
VALID_ROLES = frozenset(['admin', 'editor', 'viewer', 'guest'])
# A function that checks a user's role
def check_permission(user_role, required_action):
    # This is a conceptual check, not a real permission system
    if user_role == 'admin':
        return True
    elif user_role == 'editor' and required_action == 'edit':
        return True
    # ... etc
    return False
# You can safely pass VALID_ROLES around without worrying about it being modified.
print('editor' in VALID_ROLES) # True
# The following would raise an AttributeError, which is good!
# VALID_ROLES.add('moderator') 

How to Create and Use frozenset

Creation

You create a frozenset using the frozenset() constructor. It can take any iterable.

python frozensets-图3
(图片来源网络,侵删)
# From a list
fs1 = frozenset([1, 2, 2, 3, 4, 4, 5])
print(fs1)
# Output: frozenset({1, 2, 3, 4, 5})
# From a tuple
fs2 = frozenset(('apple', 'banana', 'cherry'))
print(fs2)
# Output: frozenset({'cherry', 'apple', 'banana'})
# From a string (each character becomes an element)
fs3 = frozenset("hello")
print(fs3)
# Output: frozenset({'e', 'h', 'l', 'o'})
# From a regular set
regular_set = {10, 20, 30}
fs4 = frozenset(regular_set)
print(fs4)
# Output: frozenset({10, 20, 30})

Common Operations (Read-Only)

Since frozenset is immutable, you can only perform operations that don't change it. These are the same as for a set, but they return a new frozenset or value instead of modifying the original.

a = frozenset([1, 2, 3, 4])
b = frozenset([3, 4, 5, 6])
# Union (elements in a or b)
union_ab = a.union(b)
print(f"Union: {union_ab}")
# Output: Union: frozenset({1, 2, 3, 4, 5, 6})
# Intersection (elements in both a and b)
intersection_ab = a.intersection(b)
print(f"Intersection: {intersection_ab}")
# Output: Intersection: frozenset({3, 4})
# Difference (elements in a but not in b)
difference_ab = a.difference(b)
print(f"Difference (a - b): {difference_ab}")
# Output: Difference (a - b): frozenset({1, 2})
# Symmetric Difference (elements in a or b but not both)
symmetric_diff_ab = a.symmetric_difference(b)
print(f"Symmetric Difference: {symmetric_diff_ab}")
# Output: Symmetric Difference: frozenset({1, 2, 5, 6})
# Membership testing
print(2 in a)          # True
print(5 not in a)       # True
# Getting the length
print(len(a))           # 4
# Checking if one is a subset of another
print(a.issubset({1, 2, 3, 4, 5})) # True

What You Can't Do

Any operation that attempts to modify the frozenset will raise an AttributeError.

my_fs = frozenset([1, 2, 3])
# These will all raise an AttributeError!
try:
    my_fs.add(4)
except AttributeError as e:
    print(f"Error: {e}") # Error: 'frozenset' object has no attribute 'add'
try:
    my_fs.remove(2)
except AttributeError as e:
    print(f"Error: {e}") # Error: 'frozenset' object has no attribute 'remove'
try:
    my_fs.discard(1)
except AttributeError as e:
    print(f"Error: {e}") # Error: 'frozenset' object has no attribute 'discard'
try:
    my_fs.pop()
except AttributeError as e:
    print(f"Error: {e}") # Error: 'frozenset' object has no attribute 'pop'
try:
    my_fs.update([4, 5])
except AttributeError as e:
    print(f"Error: {e}") # Error: 'frozenset' object has no attribute 'update'

Summary: When to Choose Which?

Use Case Best Choice Why?
You need a collection of unique items that you will frequently add/remove from. set It's mutable and has methods like .add() and .remove() for efficient modification.
You need a collection of unique items that must never change. frozenset Its immutability provides safety and guarantees that the data is constant.
You need to use a collection of items as a key in a dictionary. frozenset Dictionary keys must be hashable, and frozenset is, while set is not.
You need to store a collection of items inside another set. frozenset Sets can only contain hashable elements, and frozenset fits this requirement.

In short, use a set for most general-purpose, mutable collections of unique items. Reach for a frozenset when you need immutability, especially for dictionary keys or elements within other sets.

分享:
扫描分享到社交APP
上一篇
下一篇