网站logo

Python学习小站



一、创建字典回顶

和高中学的一样,集合的元素是互异的,我们可以像创建字典一样创建一个集合,类型是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'}