一、集合set1. 集合的特点无序元素没有索引不能通过下标访问。元素唯一自动去重重复元素只会保留一个。可变可以动态添加或删除元素。元素必须可哈希hashable即元素必须是不可变类型如int、float、str、tuple、frozenset等。2. 创建集合# 使用花括号 s1 {1, 2, 3} # 使用 set() 构造函数可迭代对象 s2 set([1, 2, 2, 3]) # 自动去重 - {1, 2, 3} s3 set(hello) # {h, e, l, o} # 空集合只能用 set()不能用 {}那是空字典 empty_set set()3. 常用方法添加元素s {1, 2} s.add(3) # {1, 2, 3} s.update([4, 5]) # 添加多个元素 - {1, 2, 3, 4, 5}删除元素s.remove(3) # 移除指定元素不存在则抛出 KeyError s.discard(4) # 移除指定元素不存在也不报错 s.pop() # 随机移除并返回一个元素集合为空时抛出 KeyError s.clear() # 清空集合集合运算方法 vs 运算符运算方法运算符说明并集a.union(b)a │ b返回两个集合的并集交集a.intersection(b)a b返回两个集合的交集差集a.difference(b)a - b返回在 a 但不在 b 的元素对称差a.symmetric_difference(b)a ^ b返回不同时属于 a 和 b 的元素a {1, 2, 3} b {3, 4, 5} print(a | b) # {1,2,3,4,5} print(a b) # {3} print(a - b) # {1,2} print(a ^ b) # {1,2,4,5}拷贝s {1, 2, 3} s2 s.copy() # 浅拷贝注意集合的浅拷贝对于元素本身是引用类型如自定义对象时内部对象仍是共享的。但由于集合元素必须可哈希大部分基本类型不可变所以实际影响较小。4. 集合推导式s {x**2 for x in range(5)} # {0, 1, 4, 9, 16}frozenset 是 Python 内置的不可变集合。一旦创建就不能添加、删除或修改任何元素。因此它可哈希可以作为字典的键也可以作为另一个集合的元素。a frozenset([1, 2, 3]) b frozenset([3, 4, 5]) print(a | b) # frozenset({1,2,3,4,5}) print(a b) # frozenset({3}) print(a - b) # frozenset({1,2}) print(a.union(b)) # 同上 print(a.issubset(b)) # False二、注意事项与常见误区1. 元素必须可哈希s {[1,2]} # TypeError: unhashable type: list s {{1:2}} # TypeError: unhashable type: dict2. 元组内的元素如果可变整个元组也不可哈希t (1, [2,3]) s {t} # TypeError: unhashable type: list3. 浅拷贝与深拷贝的区别针对集合当集合内元素是可变对象时浅拷贝会让内部对象共享。但由于集合元素必须可哈希这类场景较少见。若使用自定义类实现了哈希浅拷贝后修改对象内部状态会影响原集合中的对象。三、总结集合是高效的去重与关系运算工具适合处理无序、不重复的元素集合。冻结集合是不可变版本牺牲了修改能力换来了可作为键或集合元素的灵活性。#集合的常用方法 #1.添加元素 s1 {1,2,3,4,5,6} s1.add(999) print(fs1:{s1}) #2.删除元素 s1.remove(3) print(fs1:{s1}) #3.清空集合 s1.clear() print(fs1:{s1}) #4.集合的交集 s2 {2,5,6,7} s1.add(2) s1.add(3) s1.add(4) s1.add(5) s1.add(6) print(fs1:{s1}) print(fs2:{s2}) s3 s1 s2 print(fs3:{s3}) #5.集合的并集 s4 s1 | s2 print(fs4:{s4}) #6.集合的差集 s5 s1 - s2 #差集s1 - s2就是s1中有而s2中没有的元素 print(fs5:{s5}) #7.集合的对称差集 s6 s1 ^ s2 #对称差集s1 ^ s2就是s1和s2中不同时存在的元素 print(fs6:{s6}) #8.集合的子集和超集 s7 {2,5} print(fs7:{s7}) print(fs7是否是s1的子集:{s7.issubset(s1)})#issubset方法用于判断一个集合是否是另一个集合的子集如果是则返回True否则返回False。 print(fs1是否是s7的超集:{s1.issuperset(s7)})#issuperset方法用于判断一个集合是否是另一个集合的超集如果是则返回True否则返回False。超集就是包含另一个集合的集合。 #9.集合的长度 print(fs1的长度:{len(s1)})#len函数用于返回集合中元素的个数。 #10.集合的成员资格测试 print(f2是否在s1中:{2 in s1})#in运算符用于测试一个元素是否在集合中如果在则返回True否则返回False。 print(f10是否在s1中:{10 in s1})#in运算符用于测试一个元素是否在集合中如果在则返回True否则返回False。 #11.集合的迭代 print(s1中的元素:) for element in s1: print(element) #12.集合的复制 s8 s1 print(fs8:{s8})#直接赋值 s2 s1 只是引用传递不是复制改一个会影响另一个。 s8.add(888) print(fs8:{s8}) print(fs1:{s1}) #深拷贝和浅拷贝 #浅拷贝 s9 s1.copy()#copy方法用于创建一个集合的浅拷贝返回一个新的集合对象包含原集合中的元素。 print(fs9:{s9}) s9.add(777) print(fs9:{s9}) print(fs1:{s1})#浅拷贝修改s9不会影响s1因为s9是s1的一个新的集合对象。 #浅拷贝对于多层嵌套的集合来说内部的元素仍然是共享的如果修改了内部的元素可能会影响到原集合。 s10 {1,2,3,(4,5,9)}#集合中的元素必须是不可变类型所以元组可以作为集合的元素。 # s10[3].append(10)#元组是不可变类型不能修改所以会报错。 #浅拷贝和深拷贝对于集合来说copy方法是浅拷贝如果集合中包含可变类型的元素那么修改这些元素会影响到原集合。 #深拷贝 import copy s11 copy.deepcopy(s1)#deepcopy函数用于创建一个集合的深拷贝返回一个新的集合对象包含原集合中的元素并且对于可变类型的元素也会创建新的对象。 print(fs11:{s11}) s11.add(666) print(fs11:{s11}) print(fs1:{s1})#深拷贝修改s11不会影响s1因为s11是s1的一个新的集合对象并且对于可变类型的元素也会创建新的对象。 #冻结集合 s12 {frozenset([1,2,3]),frozenset([3,6])} print(fs12:{s12}) print(ftype(s12):{type(s12)})#集合中的元素必须是不可变类型所以frozenset可以作为集合的元素。 print(len(s12))#len函数用于返回集合中元素的个数。