Python——集合基本操作以及哈希函数

Python 中的集合(Set)是一个无序的、不包含重复元素的数据结构。集合主要用于数学上的集合操作,如并集、交集、差集和对称差集等。集合使用大括号 {} 来表示,但注意空集合不能使用 {} 表示(这会创建一个空字典),而应该使用 set() 来创建。

创建集合

1.使用大括号 {}

这是最直接的方法,但需要注意的是,空集合不能使用 {} 来创建,因为 {} 会被解释为一个空字典。对于非空集合,可以直接在大括号内列出元素,元素之间用逗号分隔。

# 创建一个非空集合  
my_set = {1, 2, 3, 'a', 'b'}  
print(my_set)  # 输出可能是 {1, 2, 3, 'a', 'b'} 或其他顺序,因为集合是无序的  
  
# 注意:空集合的创建  
empty_set = set()  # 正确的方法  
# empty_set = {}  # 这是错误的,这会创建一个空字典

2.使用 set() 函数

这是创建集合的另一种方法,包括空集合和非空集合。你可以将一个列表、元组或其他可迭代对象传递给 set() 函数,以创建一个包含相同元素的集合,但去除了重复项。

# 从列表创建集合  
my_list = [1, 2, 2, 3, 4, 4, 5]  
my_set_from_list = set(my_list)  
print(my_set_from_list)  # 输出可能是 {1, 2, 3, 4, 5}  
  
# 创建空集合  
empty_set = set()

3.从字符串创建集合

虽然不常见,但你也可以将一个字符串传递给 set() 函数,这将创建一个包含字符串中所有不同字符的集合。

# 从字符串创建集合  
my_string = "hello"  
my_set_from_string = set(my_string)  
print(my_set_from_string)  # 输出可能是 {'h', 'e', 'l', 'o'}

​​​​​​​4.使用集合推导式

类似于列表推导式,Python也支持集合推导式,允许你从一个或多个迭代器快速生成集合。

# 使用集合推导式  
my_list = [1, 2, 3, 4, 5]  
my_set = {x for x in my_list if x % 2 == 0}  
print(my_set)  # 输出可能是 {2, 4}

集合的基本操作

  • 添加元素:使用 add() 方法
  • 移除元素:使用 remove() 或 discard() 方法(remove() 如果元素不存在会抛出异常,而 discard() 不会)
  • 清空集合:使用 clear() 方法
  • 更新集合:使用 update() 方法,可以添加多个元素或另一个集合中的所有元素
my_set = {1, 2, 3}  
  
# 添加元素  
my_set.add(4)  
print(my_set)  # {1, 2, 3, 4}  
  
# 移除元素  
my_set.remove(2)  
print(my_set)  # {1, 3, 4}  
  
# 尝试移除不存在的元素(使用discard避免异常)  
my_set.discard(5)  # 不会引发异常  
  
# 清空集合  
my_set.clear()  
print(my_set)  # set()  
  
# 更新集合  
my_set.update([5, 6, 7], {8, 9})  
print(my_set)  # {5, 6, 7, 8, 9},注意顺序可能是不同的

子集和超集

在Python中,检查一个集合是否是另一个集合的子集或超集,可以使用集合类型提供的issubset()issuperset()方法。这些方法允许你轻松地进行集合之间的这种关系检查。

子集(Subset)

如果集合A的每一个元素都是集合B的元素,那么A称为B的子集。在Python中,你可以使用issubset()方法来检查一个集合是否是另一个集合的子集。

# 定义两个集合  
A = {1, 2, 3}  
B = {1, 2, 3, 4, 5}  
  
# 检查A是否是B的子集  
if A.issubset(B):  
    print("A是B的子集")  
else:  
    print("A不是B的子集")  
  
# 检查B是否是A的子集  
if B.issubset(A):  
    print("B是A的子集")  
else:  
    print("B不是A的子集")

超集(Superset)

如果集合A包含集合B的所有元素,那么A称为B的超集。在Python中,虽然没有直接命名为issuperset()的反向方法(即检查一个集合是否不是另一个集合的超集),但你可以使用issubset()方法的逻辑逆转来检查一个集合是否是另一个集合的超集。不过,实际上issuperset()方法已经提供了这种功能。

# 定义两个集合  
A = {1, 2, 3, 4, 5}  
B = {1, 2, 3}  
  
# 检查A是否是B的超集  
if A.issuperset(B):  
    print("A是B的超集")  
else:  
    print("A不是B的超集")  
  
# 检查B是否是A的超集  
if B.issuperset(A):  
    print("B是A的超集")  
else:  
    print("B不是A的超集")

特殊情况

  • 任何集合都是它自身的子集和超集。
  • 空集合是任何集合的子集。
  • 任何集合(除了它自身)都不是空集合的超集。

集合的数学操作

  • 并集:使用 | 或 union() 方法
  • 交集:使用 & 或 intersection() 方法
  • 差集:使用 - 或 difference() 方法
  • 对称差集:使用 ^ 或 symmetric_difference() 方法
set1 = {1, 2, 3, 4}  
set2 = {3, 4, 5, 6}  
  
# 并集  
print(set1 | set2)  # {1, 2, 3, 4, 5, 6}  
print(set1.union(set2))  # 同样结果  
  
# 交集  
print(set1 & set2)  # {3, 4}  
print(set1.intersection(set2))  # 同样结果  
  
# 差集  
print(set1 - set2)  # {1, 2}  
print(set1.difference(set2))  # 同样结果  
  
# 对称差集  
print(set1 ^ set2)  # {1, 2, 5, 6}  
print(set1.symmetric_difference(set2))  # 同样结果

frozenset对象

frozenset 是 Python 中的一个内置类型,它表示一个不可变的集合(set)。与普通的集合(set)相比,frozenset 的主要区别在于它不能被修改(即不支持添加、删除元素等操作)。一旦创建了 frozenset 对象,其元素集合就固定不变了。

frozenset 主要用于那些需要不可变集合的场景,比如在字典(dict)的键(key)或者集合(set)的元素中,因为字典的键和集合的元素都必须是不可变的。

创建 frozenset

你可以通过 frozenset() 构造函数来创建一个空的 frozenset,或者通过将一个可迭代对象(如列表、元组或集合)传递给 frozenset() 来创建一个包含特定元素的 frozenset

# 创建一个空的 frozenset  
empty_frozenset = frozenset()  
  
# 创建一个包含特定元素的 frozenset  
frozen_numbers = frozenset([1, 2, 3, 4, 5])  
  
# 使用集合作为输入  
set_of_numbers = {1, 2, 3, 4, 5}  
frozen_numbers_from_set = frozenset(set_of_numbers)  
  
# 使用字符串作为输入(将字符串的每个字符视为一个元素)  
frozen_chars = frozenset('hello')

frozenset 的特性

  • 不可变性:一旦创建,frozenset 中的元素就不能被添加、删除或修改。
  • 可哈希性:由于 frozenset 是不可变的,因此它是可哈希的,可以用作字典的键或集合的元素。
  • 性能:与集合(set)相比,frozenset 在一些操作上可能稍微慢一些,因为它需要保持不可变性。但在大多数情况下,这种性能差异是可以忽略不计的。

使用场景

  • 当你需要一个不可变的集合时(例如,作为字典的键)。
  • 当你需要将集合作为另一个集合的元素时(因为集合的元素必须是不可变的)。

注意事项

  • 尝试修改 frozenset(如添加、删除元素)将引发 TypeError
  • frozenset 的元素也必须是不可变的。如果尝试将包含可变元素的列表传递给 frozenset(),Python 将在尝试将列表转换为 frozenset 时抛出 TypeError,因为它无法确保 frozenset 的不可变性。然而,如果列表包含的是不可变元素(如整数、字符串、其他 frozenset 等),则转换可以成功进行。

哈希

在Python中,哈希(Hashing)是一种广泛使用的技术,尤其在字典(dict)的实现中扮演了关键角色。哈希表(Hash Table)或哈希映射(Hash Map)是一种使用哈希函数组织数据,以支持快速插入和搜索的数据结构。在Python中,字典就是基于哈希表实现的。

哈希函数

哈希函数是一个将任意长度的输入(通常称为“键”或“key”)通过某种算法转换为固定长度输出(通常称为“哈希值”或“hash”)的函数。一个好的哈希函数应具有以下特点:

  1. 一致性:相同的输入产生相同的输出。
  2. 高效性:计算哈希值的过程应该尽可能快。
  3. 均匀分布:哈希值应尽可能均匀地分布在哈希表的不同槽位中,以减少哈希冲突。

哈希冲突

哈希冲突(Hash Collision)是指两个不同的输入产生了相同的哈希值。处理哈希冲突的方法有很多,包括开放寻址法(Open Addressing)和链地址法(Chaining,Python中字典的实现就使用了这种方法)。

Python中的哈希

在Python中,许多对象都可以被哈希,这意味着它们可以用作字典的键。可哈希对象的一个关键属性是它们必须是不可变的(immutable)。这包括整数、浮点数、字符串、元组(只要元组中的元素也都是可哈希的)等。列表、集合和字典等可变类型则不是可哈希的,因此不能用作字典的键。

内置的hash()函数

Python提供了一个内置的hash()函数,可以用来获取对象的哈希值。但需要注意的是,哈希值的计算依赖于对象的内容,对于可变对象(尽管它们实际上不可哈希),在不同时间对同一个对象调用hash()可能会得到不同的结果,因为其内容可能会改变。对于不可变对象,只要内容保持不变,哈希值就会保持不变。

示例

# 对字符串进行哈希  
hash_value = hash("hello")  
print(hash_value)  # 输出该字符串的哈希值  
  
# 尝试对列表进行哈希(会引发TypeError)  
# hash_value = hash([1, 2, 3])  # TypeError: unhashable type: 'list'  
  
# 使用哈希值作为字典的键(实际开发中通常不会这么做,因为直接使用对象作为键更常见)  
# 但为了说明目的,这里用整数表示哈希值  
dict_with_hash_keys = {hash("hello"): "value for hello", hash("world"): "value for world"}  
print(dict_with_hash_keys)

需要注意的是,上面的dict_with_hash_keys示例仅仅是为了说明目的,实际中很少会直接使用哈希值作为字典的键,因为直接使用原始对象(如字符串)作为键更加直观和方便。

你可能感兴趣的:(Python笔记,python,开发语言)