一、创建字典回顶
和高中学的一样,集合的元素是互异的,我们可以像创建字典一样创建一个集合,类型是set。
x = {"I", "love", "Study"}
也可以考虑使用列表推导式构建一个集合,如:
y = {s for s in "I love Python"}
我们可以将字符串,元组,列表转化为集合,由于互异性,相同的元素会被合并。
我们可以考虑使用set函数,将返回序列转化的集合。
对于元组和列表,他们的每个元素都被作为集合中的元素,对于字符串,并不是整个字符串作为集合的元素,而是将字符串作为一个可迭代对象,迭代其中的每个元素作为集合元素。
z = set("I love studing Python")
x[0]是不被允许的,因为集合无序,因此不存在索引下标。
集合是一个可迭代对象,其中的每个元素都可以被取出来,只需要一个for循环。
for each in x:
print(each)
打印结果:
"I"
"love"
"Study"
二、用in与not in进行子集判断回顶
高中集合相互有关系,比如谁是谁的子集等等,那么怎么判断一个集合是否在另一个集合内?
可以考虑使用in 和not in关键字,他们作用于两个集合。
print("Study" in x)
print("Study" not in y)
输出:
True
True
三、集合的len函数回顶
集合也有长度,为元素个数,有时候它和原来的序列不一样。
s = [1, 1, 2, 3, 5]
print(len(s) == len(set(s)))
输出:
False
这是因为集合各个元素是相异的,列表则允许元素相同,因此前者为5,后者为4。
四、集合的拷贝回顶
如果我们想将一个集合拷贝,怎么做?
没错,copy方法,实现浅拷贝。如果s = {"1","2","1","3","4"},则下面的语句:
t = s.copy()
print(t)
输出:
{'1', '2', '4', '3'}
五、isdisjoint函数回顶
下面我们开始涉及一些集合关系的方法函数,这些集合关系判断方法有个需要注意的地方。
就是他们的参数可以是一个集合,也可以是一个可迭代对象,当为可迭代对象时,这些判断方法一般将可迭代对象自动转化为集合
怎么判断两个集合是否没有交集,也就是彼此是独立的?
考虑使用isdisjoint方法,它作用于一个集合,以另一个集合作为参数, 它判断两个集合中是否有共同元素,如果有,说明不是相互独立,返回False,反之,返回True。
s = set("Python")
print(s.isdisjoint(set("Study")))
print(s.isdisjoint(("Java")))
输出:
False (也就是有交集)
True (没有交集)
六、issubset函数回顶
怎么判断一个集合是另一个集合的子集?这很经典。
我们考虑使用issubset方法,它判断前面的集合是否是后面参数里集合的子集,是则True,不是则False。比如,当s = set("Python")时, 下面的语句:
print(s.issubset(set("I love Python")))
输出:
True
七、issuperset方法回顶
怎么判断一个集合是另一个集合的父集(超集)?考虑issuperset方法。
依然,当s = set("Python")时,下面的语句:
print(s.issuperset("Py"))
输出:
True
下面是一些集合操作函数,他们都有返回值,返回值就是满足要求的集合,但是他们都有一个共同点,就是它们不改变原有的集合。
八、并集运算union回顶
怎么得到两个集合的并集呢?
考虑union函数,union函数与众不同,可以是一个参数,也可以是两个参数。依然,当s = set("Python")时,下面的语句:
print(s.union({1, 2, 3}))
print(s.union({1, 2, 3}, "I love"))
输出:
{1, 2, 3, 'y', 't', 'h', 'o', 'P', 'n'}
{1, 2, 3, 'y', 'I', 't', 'h', ' ', 'v', 'o', 'l', 'P', 'n', 'e'}
九、差集运算difference回顶
有一个集合A和另一个集合B,对于A,其中和B元素不同的元素构成一个集合,称为A相对于B的差集。
那么怎么得到A相对于B的差集呢?考虑使用difference函数。
print(s.difference("Py"))
输出:
{'o', 't', 'n', 'h'}
十、对称差集symmetric_difference回顶
我们不是想得到A相对于B的差集,而是想将A和B中相同的元素删除,得到一个新的集合呢?
这就是A和B的对称差集,考虑使用symmetric_difference函数。
print(s.symmetric_difference("Study"))
输出:
{'d', 'S', 'h', 'u', 'o', 'P', 'n'}
十一、多集合交集运算intersection回顶
我们怎么得到多个集合的交集呢?考虑intersection函数,参数有多个,对应多个集合。
考虑intersection函数,参数有多个,对应多个集合。
print(s.intersection("Php", "Study"))
输出:
set() (表明输出是一个空集)
十二、集合的运算符回顶
运算符在集合中发挥了很重要的作用,它们同样可以实现上面的效果。
s = set("Python")
print(s <= set("Python")) #TODO 子集
print(s < set("Py")) #TODO 真子集
print(s > set("Python"))
print(s >= set("Python"))
print(s | {1, 2, 3} | set("Study")) #TODO 求并集
print(s & set("Php") & set("Study")) #TODO 求交集
print(s - set("Php") - set("Study")) #TODO 求相对于s的差集,支持多个集合
print(s ^ set("Study")) #TODO 求对称差集
注意,s <= "Study"是不被允许的。
输出:
True
False
False
True
{1, 2, 3, 'd', 'y', 'S', 't', 'h', 'o', 'u', 'P', 'n'}
set()
{'o', 'n'}
{'d', 'u', 'o', 'h', 'P', 'S', 'n'}
十三、frozeset函数回顶
一般的集合set是一个可变容器,而集合类型frozenset是一个不可变容器,里面的元素不可以被改变。
可以使用frozenset函数将可迭代对象:字符串,元组,列表,转化为不可变集合。
t = frozenset("Study")
print(t)
输出:
frozenset({'d', 'y', 'S', 't', 'u'})
十四、集合的自更新函数回顶
既然集合set类型是一个可变容器,如何给集合增加元素?
考虑update方法,它将集合set就地改造成新的集合。值得注意的是,它没有返回值。
s = set("Python")
s.update([1, 1], "Study")
print(s)
输出:
{1, 'd', 'y', 'S', 'h', 't', 'o', 'u', 'P', 'n'}
另外,update方法实质也是求并集的过程,以上面为例子,它将[1, 1]和"Study"并入s中。
如此而来,下面的方法就是将集合就地改造了。
intersection_update:得到交集, difference_update:得到相对差集,symmetric_difference_update:得到对称差集。
s = set("Python")
s.intersection_update("Php", "Pop")
print(s)
s = set("Python")
s.difference_update("Php", "Study")
print(s)
s = set("Python")
s.symmetric_difference_update("Study")
print(s)
输出:
{'P'}
{'o', 'n'}
{'d', 'S', 'h', 'o', 'u', 'P', 'n'}
十五、add方法回顶
不是想求并集,而是单纯想将某个元素插入。
考虑add方法。如果参数是字符串,那么它将字符串整体作为元素,而不是将字符串中的字符一个个取出来,这和之前的update有所不同。
s = set("Python")
s.add("45")
print(s)
输出:
{'y', 'h', 't', 'o', 'P', '45', 'n'}
十六、discard方法回顶
我们可以用remove删除集合的元素(见Section十七)。 可是如果没有这个元素,remove会报异常,想要不报出异常,怎么做?
依然给定s = set("Python")。我们可以使用discard方法删除集合的元素。
s.discard("S")
没有反应,不报错。
print(s)
输出:
{'y', 'h', 't', 'o', 'P', 'n'}
十七、集合的删除回顶
怎么删除集合中的元素呢?
我们来考虑一下pop方法,它将集合就地删除一个随机的元素。为什么是随机,这是因为集合是无序的。 值得注意的是,pop方法可以返回一个值,即为被删除的元素。
s.pop()
输出:
'y'
print(s.pop())
输出:
h
如果想删除整个集合中的元素,怎么做?考虑clear方法,它没有返回值。
s.clear()
print(s)
输出:
set()
想删除集合中指定的元素?使用remove方法。
s = set("Python")
s.remove("P") #! 参数只有一个
print(s)
输出:
{'y', 'h', 't', 'o', 'n'}
十八、hash函数回顶
python对于不可变的对象,赋予其一个属性,称为哈希值。 如果一个对象是不可变的,我们说这个对象是可哈希的,它有一个固定的哈希值,比如说字符串,数值,元组。 如果说这个对象是可变的,那么这个对象是不可哈希的,它没有哈希值。 不可变对象里面的内容是固定的,如果有另一个不可变对象的内容与之相同,那么他们的哈希值是一样的。
我们可以使用hash函数得到对象的哈希值,如果对象不可变,则抛出异常。
print(hash(1), hash(1.0), hash(1.001))
print(hash("Study"), hash((1, 2, 3)))
输出:
1 1 2305843009213441
5464733446956240229 529344067295497451
print(hash([1, 2, 3]))则会抛出异常。
这通常没有什么用,但是可以帮助我们深入理解字典和集合的一些本质。 对于字典,它要求键必须唯一,不能有两个相同的键,而且键必须可哈希,也就是说,我们不能让一个键是一个列表。
对于集合,我们要求集合每个元素必须是可哈希的,也就是说,集合的元素不能是列表,那集合的元素能不能是集合呢? 一般来说是不行的,因为集合的元素必须可哈希,对于set类型的集合当然不行,但是对于frozenset类型的集合当然是可以的。
s.add([1, 2, 3])会异常,因为不能将一个列表作为集合元素。s.add(set([1, 2, 3]))也是这样,因为不能将一个set集合作为集合元素
s = set("Python")
s.add(frozenset([1, 2, 3]))
print(s)
输出:
{'y', 'h', 't', 'o', frozenset({1, 2, 3}), 'P', 'n'}