十、集合与字典
10.1 集合
10.1.1 集合定义
Python 中的集合(set)是一种无序且元素唯一的可变数据类型。集合中的元素必须是不可变类型,这意味着列表和字典不能作为集合的元素,但字符串、数字和元组可以。
创建集合
# 创建一个空集合
empty_set = set()
# 使用花括号创建集合,但请注意,创建空集合时不能使用这种方法,因为 {} 创建的是空字典
filled_set = {1, 2, 3, 4, 5}
# 使用集合推导式
squares_set = {x**2 for x in range(10)}
10.1.2 集合操作
10.1.2.1并集
在Python中,并集是指将两个或多个集合中的所有元素合并在一起,同时去除重复的元素,只保留唯一的元素。
1.使用 |
运算符
# 定义两个集合
A = {1, 2, 3, 4}
B = {3, 4, 5, 6}
# 使用 | 运算符获取并集
union_set = A | B
print(union_set) # 输出: {1, 2, 3, 4, 5, 6}
2.使用 union()
方法
# 使用 union() 方法获取并集
union_set = A.union(B)
print(union_set) # 输出: {1, 2, 3, 4, 5, 6}
3.使用 update()
方法
如果你想在原地修改集合A,使其包含A和B的并集,可以使用 update()
方法:
# 在原地修改集合A,使其包含A和B的并集
A.update(B)
print(A) # 输出: {1, 2, 3, 4, 5, 6}
如果你想获取多个集合的并集,可以依次使用 |
运算符或 union()
方法:
# 定义更多的集合
C = {5, 6, 7, 8}
# 使用 | 运算符合并多个集合
union_set = A | B | C
# 或者使用 union() 方法
union_set = A.union(B, C)
print(union_set) # 输出: {1, 2, 3, 4, 5, 6, 7, 8}
注
无论使用哪种方法,结果都是一个包含所有集合中唯一元素的新集合。
10.1.2.2交集
在Python中,交集是指两个或多个集合共有的元素。
1 使用 &
运算符
# 定义两个集合
A = {1, 2, 3, 4}
B = {3, 4, 5, 6}
# 使用 & 运算符获取交集
intersection_set = A & B
print(intersection_set) # 输出: {3, 4}
2 使用 intersection()
方法
# 使用 intersection() 方法获取交集
intersection_set = A.intersection(B)
print(intersection_set) # 输出: {3, 4}
3 使用 intersection_update()
方法
如果你想在原地修改集合A,使其只包含A和B的交集,可以使用 intersection_update()
方法:
# 在原地修改集合A,使其只包含A和B的交集
A.intersection_update(B)
print(A) # 输出: {3, 4}
如果你想获取多个集合的交集,可以依次使用 &
运算符或 intersection()
方法:
# 定义更多的集合
C = {4, 5, 6}
# 使用 & 运算符合并多个集合
intersection_set = A & B & C
# 或者使用 intersection() 方法
intersection_set = A.intersection(B, C)
print(intersection_set) # 输出: {4}
无论使用哪种方法,结果都是一个新集合,它只包含所有给定集合共有的元素。如果集合之间没有共同元素,则结果将是一个空集合。
10.1.2.3差集
在Python中,差集是指属于一个集合而不属于另一个集合的元素组成的集合。
1 使用 -
运算符
# 定义两个集合
A = {1, 2, 3, 4}
B = {3, 4, 5, 6}
# 使用 - 运算符获取差集(在A中但不在B中)
difference_set = A - B
print(difference_set) # 输出: {1, 2}
2 使用 difference()
方法
# 使用 difference() 方法获取差集
difference_set = A.difference(B)
print(difference_set) # 输出: {1, 2}
3 使用 difference_update()
方法
如果你想在原地修改集合A,使其只包含在A中但不在B中的元素,可以使用 difference_update()
方法:
# 在原地修改集合A,使其只包含在A中但不在B中的元素
A.difference_update(B)
print(A) # 输出: {1, 2}
如果你想获取多个集合的差集,可以依次使用 -
运算符或 difference()
方法:
# 定义更多的集合
C = {1, 5, 6}
# 使用 - 运算符合并多个集合
difference_set = A - B - C
# 或者使用 difference() 方法
difference_set = A.difference(B, C)
print(difference_set) # 输出: set(),因为1也在C中,所以最终差集为空
无论使用哪种方法,结果都是一个新集合,它只包含在第一个集合中但不在其他集合中的元素。如果两个集合完全相同,那么差集将是一个空集合。如果第一个集合是其他集合的超集,那么差集也将是一个空集合。
10.1.2.4对称差集
对称差集(Symmetric Difference)是指属于两个集合之一但不同时属于两个集合的元素组成的集合。在Python中,对称差集可以通过集合的运算符或方法来获取。
1 使用 ^
运算符
# 定义两个集合
A = {1, 2, 3, 4}
B = {3, 4, 5, 6}
# 使用 ^ 运算符获取对称差集
symmetric_difference_set = A ^ B
print(symmetric_difference_set) # 输出: {1, 2, 5, 6}
2 使用 symmetric_difference()
方法
# 使用 symmetric_difference() 方法获取对称差集
symmetric_difference_set = A.symmetric_difference(B)
print(symmetric_difference_set) # 输出: {1, 2, 5, 6}
3 使用 symmetric_difference_update()
方法
如果你想在原地修改集合A,使其包含A和B的对称差集,可以使用 symmetric_difference_update()
方法:
# 在原地修改集合A,使其包含A和B的对称差集
A.symmetric_difference_update(B)
print(A) # 输出: {1, 2, 5, 6}
如果你想获取多个集合的对称差集,可以依次使用 ^
运算符或 symmetric_difference()
方法:
# 定义更多的集合
C = {5, 6, 7, 8}
# 使用 ^ 运算符合并多个集合的对称差集
symmetric_difference_set = A ^ B ^ C
# 或者使用 symmetric_difference() 方法
symmetric_difference_set = A.symmetric_difference(B).symmetric_difference(C)
print(symmetric_difference_set) # 输出: {1, 2, 7, 8}
无论使用哪种方法,结果都是一个新集合,它只包含那些仅属于A和B中的一个集合但不同时属于A和B的元素。对称差集是一个组合操作,它不关心元素的顺序,并且是交换的,即 A ^ B
和 B ^ A
的结果是相同的。
10.1.3 集合方法
add()
- 添加一个元素到集合中。clear()
- 移除集合中的所有元素。copy()
- 返回集合的一个浅拷贝。difference()
- 返回多个集合的差集。difference_update()
- 移除集合中在另一个集合中的元素。discard()
- 移除集合中的一个元素,如果该元素存在。intersection()
- 返回集合的交集。intersection_update()
- 修改集合,只保留与另一个集合共有的元素。isdisjoint()
- 如果两个集合没有共同元素,则返回True。issubset()
- 如果集合是另一个集合的子集,则返回True。issuperset()
- 如果集合是另一个集合的超集,则返回True。pop()
- 移除并返回集合中的一个随机元素。remove()
- 移除集合中的一个元素,如果该元素不存在,则会引发KeyError。symmetric_difference()
- 返回两个集合的对称差集。symmetric_difference_update()
- 用对称差集更新集合。union()
- 返回两个或多个集合的并集。update()
- 用另一个集合或迭代器中的元素更新集合。
10.1.4 集合的遍历
遍历集合中的所有元素可以通过多种方式完成,以下是一些常用的方法:
1 使用for循环
my_set = {1, 2, 3, 4, 5}
for element in my_set:
print(element)
2 使用列表推导式 虽然集合本身是无序的,但你可以通过列表推导式来遍历集合中的元素。
my_set = {1, 2, 3, 4, 5}
[element for element in my_set]
上面的代码会返回一个列表,其中包含集合中的所有元素。
3 使用next()
和迭代器
my_set = {1, 2, 3, 4, 5}
iterator = iter(my_set)
while True:
try:
element = next(iterator)
print(element)
except StopIteration:
break
上面的代码通过创建一个迭代器来遍历集合,当迭代器耗尽时,会抛出StopIteration
异常,这时循环结束。
10.1.5 集合的推导式
在Python中,集合推导式(Set Comprehensions)是一种简洁的方式来创建集合。它是基于列表推导式的概念,但是使用花括号 {}
而不是方括号 []
。集合推导式可以用来生成一个新的集合,该集合包含了对某个序列中每个元素执行操作后的结果。
集合推导式的语法如下:
{ expression for variable in iterable if condition }
expression
是你想要放在集合中的元素
variable
是循环中使用的变量
iterable
是你想要遍历的序列
if condition
是一个可选的条件表达式,用来过滤元素
例子1:生成一个包含数字平方的集合
squares = {x**2 for x in range(10)}
print(squares) # 输出 {0, 1, 4, 9, 16, 25, 36, 49, 64, 81}
例子2:生成一个包含字符串中每个字符的集合
letters = {char for char in "hello world" if char.isalpha()}
print(letters) # 输出 {'h', 'e', 'l', 'o', 'w', 'r', 'd'}
例子3:使用条件过滤
even_squares = {x**2 for x in range(10) if x**2 % 2 == 0}
print(even_squares) # 输出 {0, 4, 16, 36, 64}
需要注意的是,由于集合是无序的且不包含重复元素,所以集合推导式在处理重复元素时会自动去重。例如,如果上面的例子中的字符串"hello world"包含重复的字母,集合推导式会确保集合中每个字母只出现一次。
10.1.6 集合的特点
- 集合是无序的,因此无法通过索引来访问或修改元素。
- 集合中的元素是唯一的,重复的元素会被自动去除。
- 集合是可变的,但是它们只能包含不可变(不可变意味着不可修改)的元素。
由于集合内部实现基于哈希表,所以集合在执行成员检查(如 x in s)时通常比列表要快得多。这使得集合成为执行快速成员测试、消除重复元素和执行数学集合运算的理想选择。
10.2字典
Python 字典(dict)是一种可变容器模型,它可以存储任意类型对象,其中每个对象都存储为一个键值对。在字典中,键用于唯一地标识数据,值则表示与键相关联的数据。
10.2.1 字典的定义
字典的定义语法如下:
{key1: value1, key2: value2, ..., key_n: value_n}
{}
表示字典的开始和结束。key1
,key2
, ...,key_n
是字典中的键,它们必须是不可变的数据类型,如字符串、数字或元组。value1
,value2
, ...,value_n
是与键相关联的值,可以是任何数据类型。- 每个键值对之间用逗号
,
分隔。 例如,下面是一个包含三个键值对的字典定义:
person = {'name': '张三', 'age': 30, 'city': '北京'}
'name'
、'age'
和 'city'
是键,而 '张三'
、30
和 '北京'
是对应的值。
10.2.2 字典的常用方法
dict.clear()
- 删除字典中的所有元素。
dict.copy()
- 返回一个字典的浅复制。
dict.fromkeys(seq[, value])
- 创建一个新字典,以序列
seq
中元素做字典的键,value
为所有键对应的初始值。
- 创建一个新字典,以序列
dict.get(key[, default])
- 返回指定键的值,如果键不在字典中返回
default
的值。
- 返回指定键的值,如果键不在字典中返回
dict.items()
- 返回字典中所有的键值对,形式为列表中的元组。
dict.keys()
- 返回字典中所有的键,形式为列表。
dict.pop(key[, default])
- 删除字典中指定的键值对,并返回该键对应的值。如果键不存在,返回
default
的值,如果没有提供default
,则抛出KeyError
。
- 删除字典中指定的键值对,并返回该键对应的值。如果键不存在,返回
dict.popitem()
- 删除字典中的一个键值对,并返回该键值对。
dict.setdefault(key[, default])
- 如果键在字典中,返回键对应的值。如果键不在字典中,插入键,并设置值为
default
,然后返回default
。
- 如果键在字典中,返回键对应的值。如果键不在字典中,插入键,并设置值为
dict.update([other])
- 使用另一个字典中的键值对更新当前字典。如果当前字典中存在相同的键,则会被覆盖。
dict.values()
- 返回字典中所有的值,形式为列表。
# 字典常用方法示例
# 创建一个字典
d = {'name': 'Alice', 'age': 30, 'city': 'New York'}
# 获取键对应的值
print(d.get('name', 'Unknown')) # 输出: Alice
# 更新字典
d.update({'age': 32, 'country': 'USA'})
print(d) # 输出: {'name': 'Alice', 'age': 32, 'city': 'New York', 'country': 'USA'}
# 获取所有的键
print(d.keys()) # 输出: dict_keys(['name', 'age', 'city', 'country'])
# 获取所有的值
print(d.values()) # 输出: dict_values(['Alice', 32, 'New York', 'USA'])
# 获取所有的键值对
print(d.items()) # 输出: dict_items([('name', 'Alice'), ('age', 32), ('city', 'New York'), ('country', 'USA')])
# 删除一个键值对
d.pop('age')
print(d) # 输出: {'name': 'Alice', 'city': 'New York', 'country': 'USA'}
# 清空字典
d.clear()
print(d) # 输出: {}
10.2.3 字典的推导式
在Python中,字典推导式是一种简洁的方式来创建字典,它基于一个迭代器,按照一定的规则来生成键值对。其语法类似于列表推导式,但它在方括号内包含键值对。 字典推导式的语法如下:
{key_expression: value_expression for item in iterable}
如果需要添加一个条件,可以进一步扩展为:
{key_expression: value_expression for item in iterable if condition}
字典推导式的例子:
- 将一个列表中的元素作为键,其平方作为值来创建一个字典:
numbers = [1, 2, 3, 4, 5]
squared_dict = {x: x**2 for x in numbers}
print(squared_dict) # 输出: {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
- 使用字典推导式来过滤一个字典中的键值对,只保留值大于10的键值对:
original_dict = {'a': 5, 'b': 12, 'c': 8, 'd': 15}
filtered_dict = {k: v for k, v in original_dict.items() if v > 10}
print(filtered_dict) # 输出: {'b': 12, 'd': 15}
- 将两个列表合并为一个字典,其中第一个列表的元素作为键,第二个列表的元素作为值:
keys = ['a', 'b', 'c']
values = [1, 2, 3]
combined_dict = {k: v for k, v in zip(keys, values)}
print(combined_dict) # 输出: {'a': 1, 'b': 2, 'c': 3}
10.2.4 字典的遍历
字典的遍历可以通过几种方式完成,以下是一些常用的方法:
- 遍历字典的键(keys):
d = {'a': 1, 'b': 2, 'c': 3}
for key in d.keys():
print(key) # 输出: a, b, c
- 遍历字典的值(values):
for value in d.values():
print(value) # 输出: 1, 2, 3
- 遍历字典的键值对(items):
for key, value in d.items():
print(key, value) # 输出: a 1, b 2, c 3
- 直接遍历字典,默认遍历的是键:
for key in d:
print(key) # 输出: a, b, c
综合示例遍历字典
d = {'a': 1, 'b': 2, 'c': 3}
# 遍历字典的键
print("Keys:")
for key in d:
print(key)
# 遍历字典的值
print("\nValues:")
for value in d.values():
print(value)
# 遍历字典的键值对
print("\nItems (Key: Value):")
for key, value in d.items():
print(f"{key}: {value}")
输出结果为:
Keys:
a
b
c
Values:
1
2
3
Items (Key: Value):
a: 1
b: 2
c: 3
10.2.5 字典的特点
字典(Dictionary)在Python中是一种非常强大和灵活的数据结构,它具有以下特点:
- 键值对存储:字典以键值对(key-value pairs)的形式存储数据,每个键对应一个值。
- 键的唯一性:在同一个字典中,每个键必须是唯一的,但是值不必唯一。
- 动态大小:字典可以根据需要动态地添加和删除键值对,不需要预先定义大小。
- 无序性:在Python 3.6之前,字典是无序的,即键值对的顺序是不固定的。从Python 3.7开始,字典是有序的,它们会按照键值对被添加的顺序来维护顺序。
- 键的不可变性:字典的键必须是不可变的数据类型,如字符串、数字或元组。不可变意味着这些类型的值一旦创建,就不能更改。
- 值的可变性:字典的值可以是任何数据类型,包括可变的列表、集合、字典等。
- 快速访问:字典通过哈希表实现,因此对于查找、插入和删除操作,通常可以在常数时间内完成,即与字典中元素的数量无关。
具体特点:
- 灵活的键操作:可以通过键来快速访问、更新或删除字典中的值。
- 方法丰富:字典提供了许多内置方法,如
clear()
,copy()
,fromkeys()
,get()
,items()
,keys()
,pop()
,popitem()
,setdefault()
,update()
和values()
,用于操作和查询字典。 - 推导式支持:可以使用字典推导式来简洁地创建字典。
- 遍历能力:可以方便地遍历字典的键、值或键值对。