集合的概述:
python中集合的概念与数学中的集合是一致的,不允许有重复元素
python集合类型中可以分为set(可变数据类型)、frozenset(不可变数据类型),本文主要学习set的使用。
set:
A set object is an unordered collection of distinct hashable objects
一个set对象是不同的可hash对象的无序集合不支持索引跟切片。
这里的hashable(可hash性)
hashable
An object is hashable if it has a hash value which never changes during
its lifetime (it needs a `__hash__()` method),
and can be compared to other objects (it needs an `__eq__()` method).
Hashable objects which compare equal must have the same hash value.
如果一个对象的哈希值在其生命周期内从未改变(它需要’ hash() ‘方法),并且可以与其他对象进行比较(它需要’ eq() '方法),则该对象是可哈希的。比较相等的哈希对象必须具有相同的哈希值。
学过java的同学可能当时还背过上面这段话相关的面试题:重写equals方法为啥用重写hashcode?
注意:
eq():用于比较两个对象是否相等
hash():实际上就是哈希函数(散列函数),返回经过运算得到的哈希值
Most of Python’s immutable built-in objects are hashable; mutable containers (such as lists or dictionaries) are not; immutable containers (such as tuples and frozensets) are only hashable if their elements are hashable.
Objects which are instances of user-defined classes are hashable by default.
They all compare unequal (except with themselves), and their hash value is derived from their [`id()`]
大多数Python的不可变对象都是可哈希的;可变对象(如列表或字典)则不是;不可变容器(如元组和frozenset)只有在其元素是可哈希的情况下才是可哈希的。默认情况下,作为用户定义类实例的对象是可哈希的。它们的比较都是不相等的(除了它们自己),它们的哈希值来自于它们的id()方法
对于可变对象而言,比如一个列表,更改列表的值,但是对象的地址本身是不变的,也就是说不同的Key,映射到了相同的Value,这显然是不符合哈希值的特性的,即出现了哈希运算里面的冲突,也就是不可hash。
set 集合的创建
格式1:set()
set() -> new empty set object
set(iterable) -> new set object
使用说明
str1 = "hello"
set1 = set()
print(set1) #输出:set()
print(set(str1)) #输出:{'e', 'h', 'o', 'l'}
tuple1 = 1, 2, 3, 4
set2 = set(tuple1) #{1, 2, 3, 4}
#set2 = set(1, 2, 3, 4) #报错: set expected at most 1 argument, got 4
print(set2)
set3 = set(range(1, 5))
注意 set函数是接受一个可迭代的对象,且传入参数就只能1个,你将元组直接传入,python会当成一个个来参数处理呀
格式2:变量名={元素,元素…}
使用说明:
set1={1,2,3,'hello'}
print(set1)
#set2={1,2,3,['hello','python']} #报错 TypeError: unhashable type: 'list'
print(set2)
set3={1,2,3,'hello',1}
print(set3) #输出{'hello', 1, 2, 3} 自动去重不报错
强调: set对象是不同的可hash对象的无序集合
推导式创建
set4 = {num for num in range(1, 100) if num % 2 == 0}
print(set4)
set集合的逻辑判断:
集合元素的判断:
in / not in
#判断集合set1与set2是否相交
set1.isdisjoint(set2)
#判断set1是否是set2的子集
set1.issubset(set2) 等价于 set <= othe
#判断set1是不是set2的超集
set1.issuperset(set2) 等价于 set >= other
举例说明:
set1={1,2,3,4}
set2={5,6,7,3}
#判断集合set1与set2是否相交,返回True 与false
print(set1.isdisjoint(set2))
#判断set1是否是set2的子集
print(set1.issubset(set2) )
print(set1 <= set2)
#判断set1是不是set2的超集
print(set1.issuperset(set2))
print(set1>=set2)
set集合的运算
# 集合的交集、并集、差集、对称差运算
union (*others) # 等价于 set | other | ...
intersection(*others) #等价于 set & other & ...
difference(*others) #等价于 set - other - ...
symmetric_difference(*other) #等价于 set ^ other
set1={1,2,3,4}
set2={5,6,7,3}
print(set1 & set2)
# print(set1.intersection(set2))
print(set1 | set2)
# print(set1.union(set2))
print(set1 - set2)
# print(set1.difference(set2))
print(set1 ^ set2)
# print(set1.symmetric_difference(set2))
输出结果
{3}
{1, 2, 3, 4, 5, 6, 7}
{1, 2, 4}
{1, 2, 4, 5, 6, 7}
*other 可以说一个或多个可迭代对象(字符串、元组、列表、字典都可以)
set的增删改:
与list一样set也支持增删改查操作,但set是无序的,所以不支持列表中这种运算
- 没有下标,所以不支持切片运算、索引运算、index、insert这样的方法呀。
- 不支持set +set运算 而是通过 union ()方法
- 不支持* 运算 ,set元素不重复嘛。
set 增加元素
set1.add(元素)
set1.update(*others) 等价运算符 set |= other | ...
非等价运算符:update(*others)方法将接受任何可迭代的作为参数
举例:
set1 = {1, 2, 3}
set1.add('hello')
print(set1)
set1.update({'A', 'B'},{'C', 'D'})
set2 = set(range(1, 10))
set2.update([11, 12])
print(set1)
print(set2)
set 更新元素
set中更新元素,主要是通过两个集合之间的交集、并集、差集来实现集合的更新。
#只更新交集部分
intersection_update(*others) 等价运算符版: set &= other & ...
示例:
set1 = {1, 2, 3}
set2 = {'A', 'B', 1, 2}
print(set1)
set1.intersection_update(set2)
print(set1, set2)
#set1 &= set2
输出结果:
{1, 2, 3}
{1, 2} {1, 'B', 2, 'A'}
#更新set1集合,删除在set2集合中找到的元素。
difference_update(*others) 等价运算符版: set -= other | ...
示例:
set1 = {1, 2, 3}
set2 = {'A', 'B', 1, 2}
print(set1)
set1.difference_update(set2)
print(set1, set2)
#set1 -= set2
输出结果:
{1, 2, 3}
{3} {'B', 'A', 2, 1}
#对称差集更新
symmetric_difference_update(*other) 等价运算符版:set ^= other
示例:
set1 = {1, 2, 3}
set2 = {'A', 'B', 1, 2}
print(set1)
set1.symmetric_difference_update(set2)
print(set1, set2)
#set1 ^= set2
输出结果:
{1, 2, 3}
{3, 'A', 'B'} {1, 2, 'A', 'B'}
注意: 非运算符版本的
intersection_update()
、difference_update()
和symmetric_difference_update()
方法将接受任何可迭代的作为参数。
set删除元素:
remove
(元素) ,删除元素不存在会报KeyError
discard
(元素) ,删除元素,元素存在才会删除,不存在也不会报错
pop
(),从集合中随机移除一个元素,如果set是个空,则会报KeyError
set1 = {1, 2, 3, 4, 5, 2}
print(set1)
set1.remove(1)
# set1.remove(7) 报KeyError
print(set1)
set1.discard(7) # 不存在也不报错
set1.discard(2)
print(set1)
set1.pop()
print(set1)
注意呀 set是无序的所有没有像list.pop(i)这种方法呀
set的聚合函数:
支持max()、min()、len()
注意 max、min中只支持一种数据类型,如果set中有多种数据类型,max、min会报错
set的遍历:
-
for in 遍历
set1 = {2, 1, 9, 4, 5, 2} for s1 in set1: print(s1,end=' ')
-
enumerate()
set1 = {2, 1, 9, 4, 5, 2} for index, num in enumerate(set1): print(f"{index}:{num}")
上面这个index不是set1中的索引,也不是set1的插入顺序呀,是enumerate 对set中元素执行默认排序生成的一个索引呀。
-
iter()遍历
set1 = {2, 1, 9, 4, 5, 2} for num in iter(set1): print(num,end=' ')