集合推导式是Python中的一种特性,它可以用来从已有的数据序列(如列表、集合或字典)创建新的数据序列。
1. Python中集合(set)的定义
- 集合是无序的
- 集合的元素不能重复,所以集合中的元素是唯一的
- 集合中不能出现可变的数据类型,集合中存放的数据类型:number,string,tuple,冰冻集合
- 可以直接使用 {} 来定义集合
- 可以使用 set{} 进行集合的定义和转换
- 使用集合推导式完成集合的定义
2. Python中集合(set)的特性
在Python中,集合(set)是一个无序的不重复元素序列,它具有以下特性:
- 元素的值不能改变,但可以删除和增加
- 集合中无重复数据
- 集合中的数据是无序的
- 集合内部会对数据元素自动按一定顺序处理,但不是自动排序
- 集合中没有切片和索引
3. Python中集合(set)的操作
3.1 定义集合
vars = {123,'abc',False,'love',True,(1, 2, 3),0,3.145,123}
print(vars) # {False, True, 3.145, 'love', (1, 2, 3), 123, 'abc'}
# 从返回结果,我们发现:
# 1、无序
# 2、布尔类型true表示为1,False表示为0,布尔和数字只能存在一个,Flase在集合中表示为0,所以False和0只能存在一个
# 3、元素的值不能重复
3.2 集合转换
original_list = [1,2,3,4]
new_set = set(original_list)
print(new_set) # {1, 2, 3, 4}
original_dict = {'a':1,'b':2,'c':3}
new_set = set(original_dict)
print(new_set) # 返回字典的Key:{'c', 'b', 'a'}
original_tuple = (('a',1),('b',2),('c',3))
new_set = set(original_tuple)
print(new_set) # 返回:{('b', 2), ('c', 3), ('a', 1)}
3.2 添加元素
3.2.1 添加元素到集合 add()
vars = {False, True, 3.145, 'love', (1, 2, 3), 123, 'abc'}
res = vars.add('def')
print(res) # None
print(vars) # {False, True, 3.145, 'abc', 'def', (1, 2, 3), 'love', 123}
首先,我们需要明确Python集合(set)的add
方法并不会返回集合本身,而是返回None。所以当你尝试打印res
,其结果将会是None
。
此外,add
方法添加元素到集合中并不会改变原始集合的顺序。同时,集合中的元素是唯一的,如果尝试添加一个已经存在的元素,那么该操作不会有任何效果。
vars = {False, True, 3.145, 'love', 'def',(1, 2, 3), 123, 'abc'}
res = vars.add('def')
print(res)
print(vars)
# 返回结果:
# None
# {False, True, 3.145, (1, 2, 3), 'love', 'def', 'abc', 123}
3.2.2 合并两个集合 update()
在Python中,集合(set)的update
方法用于合并两个集合,而不是删除元素。它会添加所有不在原始集合中的元素,而不会改变原始集合中已经存在的元素。
vars = {False, True, 3.145, 'love', 'def',(1, 2, 3), 123, 'abc'}
res = vars.update({3.14,tuple([1,1,2,3,5,8])})
print(res) # 返回:None
print(vars) # 返回:{False, True, 3.145, 'def', 'love', 3.14, (1, 1, 2, 3, 5, 8), (1, 2, 3), 'abc', 123}
在Python中,集合(set)是一个无序的不重复元素序列。集合中的元素必须是可哈希的,这意味着它们必须是不可变的。这意味着你可以在集合中存储整数、浮点数、字符串、元组等,但你不能存储列表或其他可变的数据结构,因为它们不是不可变的。所以,为了解决这个问题,你可以将列表转换为元组,因为元组是不可变的并且是可哈希的。
3.3 删除元素
3.3.1 随机删除一个元素并返回:pop()
vars = {False, True, 3.145, 'love', 'def',(1, 2, 3), 123, 'abc'}
del_element = vars.pop()
print(del_element)
print(vars)
# 返回结果:
# False
# {True, 3.145, 'def', (1, 2, 3), 'love', 'abc', 123}
3.3.2 指定删除集合中的元素:remove()、discard()
remove() 返回None,不存在则报错
res = vars.remove('abc')
print(res)
print(vars)
vars = {False, True, 3.145, 'love', 'def',(1, 2, 3), 123, 'abc'}
del_element = vars.remove('abc') # remove()返回none,不存在则报错
print(del_element)
print(vars)
# 返回结果:
# None
# {False, True, 'love', 3.145, 'def', (1, 2, 3), 123}
discard() 返回None,不存在不报错
vars = {False, True, 3.145, 'love', 'def',(1, 2, 3), 123, 'abc'}
del_element = vars.discard('aaa') # remove()返回none,不存在也不会报错
print(del_element)
print(vars)
# 返回结果:
# None
# {False, True, 'def', 3.145, 'love', (1, 2, 3), 123, 'abc'}
3.3.3 清空集合 clear()
vars = {False, True, 3.145, 'love', 'def',(1, 2, 3), 123, 'abc'}
res = vars.clear()
print(res) # 返回:None
print(vars) # 返回:set()
3.4 计算元素个数 len()
vars = {False, True, 3.145, 'love', 'def',(1, 2, 3), 123, 'abc'}
res = len(vars)
print(res) # 返回:8
3.5 判断元素是否存在 in、not in
vars = {False, True, 3.145, 'love', 'def',(1, 2, 3), 123, 'abc'}
res1 = 123 in vars
res2 = 'aaa' not in vars
print(res1) # 返回:True
print(res2) # 返回:True
3.6 集合的拷贝 copy()
vars = {False, True, 3.145, 'love', 'def',(1, 2, 3), 123, 'abc'}
res = vars.copy()
print(res) # 返回:{False, True, 'def', 3.145, (1, 2, 3), 'abc', 'love', 123}
当前集合中的浅拷贝并不存在深拷贝的问题。因为集合中的元素都是不可变的,包括元组和冰冻集合不存在拷贝后,对集合中不可变的二级容器进行操作。
3.7 冰冻集合
在Python中,"冰冻集合"(Frozenset)是一个不可变的集合类型。它与普通的可变集合(Set)相对,是不可变的意味着一旦创建了冰冻集合,就不能更改它的内容。
3.7.1 冰冻集合的一些特性
-
不可变性:冰冻集合是不可变的,一旦创建就不能更改。这意味着你不能添加、删除或修改冰冻集合中的元素。
-
线程安全:由于冰冻集合是不可变的,它们在多线程环境中是线程安全的。在并发编程中,这使得它们成为存储共享数据的可靠选择。
-
哈希性:冰冻集合是哈希的,这意味着它们可以作为字典的键或其他集合的元素。由于它们是不可变的,所以它们的哈希值不会改变。
3.7.2 冰冻集合的创建
你可以使用内置的frozenset()
函数或花括号{}
来创建冰冻集合。例如:
s = frozenset([1, 2, 3, 4])
t = frozenset((5, 6, 7, 8))
u = frozenset({9, 10, 11, 12})
3.7.3 冰冻集合的作用
- 由于冰冻集合是不可变的,它们经常用于创建只读的数据结构,如哈希表中的键或作为字典的键。由于它们是不可变的,所以它们在多线程环境中是安全的,可以作为线程之间的共享数据。
- 冰冻集合也常用于函数参数的默认值,因为它们是不可变的,所以可以确保函数参数的一致性。
3.7.6 与可变集合的区别
- 可变集合(Set)与冰冻集合的主要区别在于可变性。可变集合是可变的,这意味着你可以添加、删除或修改集合中的元素。与此相反,冰冻集合一旦创建就是不可变的。
示例:
下面是一个简单的示例,演示了如何使用冰冻集合:
# 创建一个冰冻集合
fs = frozenset([1, 2, 3, 4])
print(fs) # 输出:frozenset([1, 2, 3, 4])
# 由于冰冻集合是不可变的,尝试修改它会导致错误
# fs.add(5) # AttributeError: 'frozenset' object has no attribute 'add'
总结,冰冻集合在Python中提供了一种不可变集合的类型,它常用于创建只读的数据结构、作为字典的键或在多线程环境中安全地存储数据。
4. Python中集合(set)的运算
4.1 交集:使用 & 或 set.intersection() 或 set.intersection_update()
vars1 = {'郭富城','达尔文','张学友','黎明','爱因斯坦'}
vars2 = {'赵四','刘能','小沈阳','宋小宝','爱因斯坦','达尔文'}
# 使用 & 求两个集合相交部分
res = vars2 & vars1
print(res) # {'达尔文', '爱因斯坦'}
# 使用 intersection() 求两个集合相交部分
res = vars2.intersection(vars1)
print(res) # {'达尔文', '爱因斯坦'}
set.intersection() 返回交集的结果,产生新的集合。
vars1 = {'郭富城','达尔文','张学友','黎明','爱因斯坦'}
vars2 = {'赵四','刘能','小沈阳','宋小宝','爱因斯坦','达尔文'}
# 使用 intersection_update() 求两个集合相交部分
res = vars1.intersection_update(vars2)
print(res) # None
print(vars1) # {'爱因斯坦', '达尔文'}
set.intersection_update()
方法用于更新集合 vars1
,将其修改为 vars1
和 vars2
的交集。如果 vars1
中存在某个元素不在 vars2
中,则该元素会被从 vars1
中移除。如果存在相同的元素在两个集合中,它们都会被保留。
set.intersection_update() 没有返回值
4.2 并集:使用 | 或 union() 或 update()
vars1 = {'郭富城','达尔文','张学友','黎明','爱因斯坦'}
vars2 = {'赵四','刘能','小沈阳','宋小宝','爱因斯坦','达尔文'}
# 使用 | 求两个集合的并集,也就是把两个集合的元素全部集中起来(去重)
res = vars1 | vars2
print(res) # {'刘能', '郭富城', '赵四', '达尔文', '爱因斯坦', '宋小宝', '小沈阳', '黎明', '张学友'}
vars1 = {'郭富城','达尔文','张学友','黎明','爱因斯坦'}
vars2 = {'赵四','刘能','小沈阳','宋小宝','爱因斯坦','达尔文'}
# 使用 set.union() 求两个集合的并集,返回一个新的集合。
res = vars1.union(vars2)
print(res) # {'刘能', '郭富城', '赵四', '达尔文', '爱因斯坦', '宋小宝', '小沈阳', '黎明', '张学友'}
vars1 = {'郭富城','达尔文','张学友','黎明','爱因斯坦'}
vars2 = {'赵四','刘能','小沈阳','宋小宝','爱因斯坦','达尔文'}
# 使用 set.update() 求两个集合的并集,并把结果赋值给第一个集合。
res = vars1.update(vars2)
print(vars1) # {'刘能', '郭富城', '赵四', '达尔文', '爱因斯坦', '宋小宝', '小沈阳', '黎明', '张学友'}
4.3 差集:使用 - 或 set.diffrence() 或 set.diffrence_update()
vars1 = {'郭富城','达尔文','张学友','黎明','爱因斯坦'}
vars2 = {'赵四','刘能','小沈阳','宋小宝','爱因斯坦','达尔文'}
# 使用 - 求两个集合的差集。
res = vars1 - vars2 # vars1里有,vars2里没有的
print(res) # {'张学友', '黎明', '郭富城'}
res = vars2 - vars1 # vars2里有,vars1里没有的
print(res) # {'赵四', '小沈阳', '刘能', '宋小宝'}
vars1 = {'郭富城','达尔文','张学友','黎明','爱因斯坦'}
vars2 = {'赵四','刘能','小沈阳','宋小宝','爱因斯坦','达尔文'}
# 使用 set.difference() 求两个集合的差集,并返回一个新的差集
res = vars1.difference(vars2) # vars1里有,vars2里没有的
print(res) # {'张学友', '黎明', '郭富城'}
res = vars2.difference(vars1) # vars2里有,vars1里没有的
print(res) # {'赵四', '小沈阳', '刘能', '宋小宝'}
vars1 = {'郭富城','达尔文','张学友','黎明','爱因斯坦'}
vars2 = {'赵四','刘能','小沈阳','宋小宝','爱因斯坦','达尔文'}
# 使用 set.difference() 求两个集合的差集,并把结果赋值vars1。
res = vars1.difference_update(vars2) # vars1里有,vars2里没有的
print(vars1) # {'张学友', '黎明', '郭富城'}
4.4 对称差集:使用^ 或 symmtric_difference() 或symmetric_difference_update()
- 对称差集,也称为对称差,是集合运算中的一种概念。对于两个集合A和B,它们的对称差集定义为A和B中所有不属于A∩B的元素的集合,记为A△B。换句话说,A△B包含的是那些属于A或者属于B,但不同时属于两者的元素。数学表达式为:A△B = (A∪B) - (A∩B) 或者 A△B = (A - B) ∪ (B - A)。
- 这个概念在多个领域中有应用,例如在计算机科学中,它可以用于处理和操作数据结构,如集合。在Python中,可以使
用 ^ 或
symmmetric_difference()或symmmetric_difference_update()方法来计算两个集合的对称差集。这个方法返回一个新的集合,不会修改原始集合。
vars1 = {'郭富城','达尔文','张学友','黎明','爱因斯坦'}
vars2 = {'赵四','刘能','小沈阳','宋小宝','爱因斯坦','达尔文'}
# 使用 ^ 求两个集合的对称差集,并返回一个新集合。
res = vars1 ^ vars2
print(res) # {'赵四', '郭富城', '黎明', '小沈阳', '刘能', '宋小宝', '张学友'}
vars1 = {'郭富城','达尔文','张学友','黎明','爱因斯坦'}
vars2 = {'赵四','刘能','小沈阳','宋小宝','爱因斯坦','达尔文'}
# 使用 set.symmetric_difference() 求两个集合的对称差集,并返回一个新集合。
res = vars1.symmetric_difference(vars2)
print(res) # {'赵四', '郭富城', '黎明', '小沈阳', '刘能', '宋小宝', '张学友'}
vars1 = {'郭富城','达尔文','张学友','黎明','爱因斯坦'}
vars2 = {'赵四','刘能','小沈阳','宋小宝','爱因斯坦','达尔文'}
# 使用 set.symmetric_difference_update() 求两个集合的对称差集,并把结果赋值给vars1。
res = vars1.symmetric_difference_update(vars2) # 返回:None
print(vars1) # {'赵四', '郭富城', '黎明', '小沈阳', '刘能', '宋小宝', '张学友'}
5. 集合推导式
5.1 普通推导式
varset = {1,2,3,4}
newset = {i<<2 for i in varset}
print(newset) # {8, 16, 4, 12}
# 一个整数的二进制向左移动两位,原数(十进制)与新数的关系是:新数=原数×4
# 因为集合中的元素是无序的,所以不一定是{4, 8, 12, 16}
5.2 带有条件表达式的推导式
varset = {1,2,3,4}
newset = {i<<2 for i in varset if i%2==0}
print(newset) # {8, 16}
5.3 带有多循环的集合推导式
varsl = {1,2,3}
vars2 = {4,5,6}
newset = set()
for i in varsl:
for j in vars2:
print(i,j)
newset.add(i+j)
print(newset)
# 返回结果:
# 1 4
# 1 5
# 1 6
# 2 4
# 2 5
# 2 6
# 3 4
# 3 5
# 3 6
# {5, 6, 7, 8, 9}
优化多循环为集合推导式:
varsl = {1,2,3}
vars2 = {4,5,6}
newset = {i+j for i in varsl for j in vars2}
print(newset) # {5, 6, 7, 8, 9}
5.4 带条件表达式的多循环的集合推导式
varsl = {1,2,3}
vars2 = {4,5,6}
newset = {i+j for i in varsl for j in vars2 if i%2==0 and j%2==0}
print(newset) # {8, 6}