社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

6000+字:详解python集合set,建议珍藏!!

Python极客专栏 • 3 年前 • 450 次点击  

近期福利:手把手教你白嫖1年阿里云服务器(点击查看)



Python的多种不同类型的对象:字符串、列表、元组、字典。它们有各自的特点:

  • 字符串str:存在索引,字符串中的元素是可以重复的,元素是不可变,不能修改的
  • 列表list:也能够进行索引和切片操作,元素可以修改,是可变的
  • 元组tuple:可以看成是不能进行修改的“列表”;元素不能直接修改,也可以进行索引和切片操作,类似列表
  • 字典:Python中十分常用,键值对组成,键必须是比可变的数据类型(比如元组),值可以是任意数据;字典是无序的

如果说元组是列表和字符串的杂合体,那么集合可以看做是列表和字典的杂合体

Python连载文章

Python入门的连载文章:

本文的整体目录结构:

集合创建

集合set的创建有两种方法:

  1. 通过set函数创建,空集合只能用这种方式
  2. 通过{}来创建

空集合

s1 = set()  # 空集合
s1
set()
type(s1)
set

注意:空集合必须使用set函数来创建,因为{}是用来创建空字典的

非空集合

使用花括号创建

s2 = {1,2,3,4}  
s2
{1, 2, 3, 4}
type(s2)
set

使用set函数创建

s3 = set([9,8,7,6])  # 将元素用列表装起来,set只能有一个参数
s3
{6, 7, 8, 9}
type(s3)
set
s4 = set((11,22,33,44))  # 用元组装起来
s4
{11, 22, 33, 44}

集合的元素不能重复

集合中的元素是不能重复的;如果有重复的元素,集合会自动去重。这是一种非常高效的去重方式

s5 = set([1234321])  # 存在重复数据
s5
{1, 2, 3, 4}

产生的数据中自动将重复的去掉了

type(s5) # 查看类型
set
s6 = set("javascript"# 字符串中a重复了,自动去重
s6



    
{'a', 'c', 'i', 'j', 'p', 'r', 's', 't', 'v'}

特别点

当我们创建集合的时候,需要注意数据类型

s7 = {"python", [1,2,3,"java"], {"name":"xiaoming","age":19},100}
s7
---------------------------------------------------------------------------

TypeError Traceback (most recent call last)

in
----> 1 s7 = {"python", [1,2,3,"java"], {"name":"xiaoming","age":19},100}
2 s7


TypeError: unhashable type: 'list'

上面报错中的关键词:unhashable,中文是不可哈希的。意思是创建的时候存在不可哈希的数据类型:列表 。我们可以记住:

  • 不可哈希,即代表可变,比如列表、字典等
  • 可哈希,即代表不可变,比如字符串,字典的键等

当我们创建集合的时候,元素必须是可哈希的

set集合方法

首先我们通过dir(set)来查看集合的操作方法:

print(dir(set))
['__and__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__iand__', '__init__', '__init_subclass__', '__ior__', '__isub__', '__iter__', '__ixor__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__or__', '__rand__', '__reduce__', '__reduce_ex__', '__repr__', '__ror__', '__rsub__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__xor__', 'add', 'clear', 'copy', 'difference', 'difference_update', 'discard', 'intersection', 'intersection_update', 'isdisjoint', 'issubset', 'issuperset', 'pop', 'remove', 'symmetric_difference', 'symmetric_difference_update', 'union', 'update']

add-添加不可变元素

集合中添加元素

s3  # 原集合
{6, 7, 8, 9}
s3.add(1)  # 添加1
s3
{1, 6, 7, 8, 9}
s3.add(2)  # 添加2
s3
{1, 2, 6, 7, 8, 9}
s3.add([1,3,5])
---------------------------------------------------------------------------

TypeError Traceback (most recent call last)

in
----> 1 s3.add([1,3,5])


TypeError: unhashable type: 'list'

报错提示:列表是不可哈希,也就是可变类型的。之前我们说过:集合中的元素都是可哈希(不可变类型),所以不能直接添加

list1 = [1,3


    
,5]
tuple1 = tuple(list1)  # 列表转成元组,元组是不可变的

tuple1
(1, 3, 5)
s3.add(tuple1)  # 添加元组
s3
{(1, 3, 5), 1, 2, 6, 7, 8, 9}

update-更新集合

更新集合中的元素,将两个集合中的元素组合在一起

# 创建两个集合,有相同的元素“python”

s8 = set(["python","java","c"])
s9 = set(["python","go","javascript","html"])
s8.update(s9)
s8  
{'c', 'go', 'html', 'java', 'javascript', 'python'}

生成的数据中自动将python去重了

s9  # s9还是没有变化的
{'go', 'html', 'javascript', 'python'}

update的参数不仅仅是集合,它的参数是不可变数据类型:

help(set.update)  # 查看方法的文档信息
Help on method_descriptor:

update(...)
Update a set with the union of itself and others.
s9.update("hello")
s9
{'e', 'go', 'h', 'html', 'javascript', 'l', 'o', 'python'}
s9.update((7,8,9))
s9
{7, 8, 9, 'e', 'go', 'h', 'html', 'javascript', 'l', 'o', 'python'}

pop-随机删除

随机删除一个元素,并且返回删除的结果。pop不能指定参数,也就是不能指定想要删除的元素

s9.pop()
'python'
s9.pop()
'html'
s9.pop("python")  # 不能带参数
---------------------------------------------------------------------------

TypeError Traceback (most recent call last)

in
----> 1 s9.pop("python") # 不能带参数


TypeError: pop() takes no arguments (1 given)

remove-指定删除

删除的元素必须在集合中。如果不存在,则会报错

s8
{'c', 'go', 'html', 'java', 'javascript', 'python'}
s8.remove("go")
s8  # 结果显示go被删除了
{'c', 'html', 'java', 'javascript', 'python'}
s8.remove("go")   # 再次删除go就会报错,因为go已经不存在了
---------------------------------------------------------------------------

KeyError Traceback (most recent call last)

in
----> 1 s8.remove("go") # 再次删除go就会报错,因为go已经不存在了


KeyError: 'go'

discard-指定删除

指定删除某个元素,如果元素不存在,也不会报错。

s8  # 原数据
{'c', 'html', 'java', 'javascript', 'python'}
s8.discard("html")
s8  # 删除后的数据
{'c', 'java', 'javascript', 'python'}
s8
{'c', 'java', 'javascript', 'python'}
s8.discard("go")

上面的结果表明:如果删除的元素不存在,也不会报错。这个是和remove不一样的地方

clear-清空集合

删除集合中的全部元素

s8
{'c', 'java', 'javascript', 'python'}
s8.clear()  # 清空了集合
s8
set()
bool(s8)  # bool值为False
False

不变的集合-frozenset()

上面通过set方法创建的集合,我们了解到:集合是可变的,也就是可修改的,或者说不可哈希的。

实际上还有一种方式创建的集合是不可变的:frozenset(),可以理解成冻集合,所以就不能进行修改等操作啦。

f_set = frozenset("python")
f_set
frozenset({'h', 'n', 'o', 'p', 't', 'y'})

我们查看下这个冻集合的操作方法

print(dir(f_set))  # 冻集合
['__and__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__or__', '__rand__', '__reduce__', '__reduce_ex__', '__repr__', '__ror__', '__rsub__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__xor__', 'copy', 'difference', 'intersection', 'isdisjoint', 'issubset', 'issuperset', 'symmetric_difference', 'union']
print(dir(s9))  # set集合,非冻集合
['__and__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__iand__', '__init__', '__init_subclass__', '__ior__', '__isub__', '__iter__', '__ixor__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__or__', '__rand__', '__reduce__', '__reduce_ex__', '__repr__', '__ror__', '__rsub__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__xor__', 'add', 'clear', 'copy', 'difference', 'difference_update', 'discard', 'intersection', 'intersection_update', 'isdisjoint', 'issubset', 'issuperset', 'pop', 'remove', 'symmetric_difference', 'symmetric_difference_update', 'union', 'update']

通过对比两种集合的操作方法,我们发现:冻集合中明显是少了很多增加、删除等方法,所以冻集合是不可变的

集合运算

在这个小节中介绍的是集合中的各种运算,比如:交集、并集、补集等

in-元素判断

s5
{1, 2, 3, 4}
1


    
 in s5
True
6 in s5
False

issubset-子集与issuperset-超集

A如果是B的子集,那么B就是A的超集;也就说A的元素全部在B中

s10 = {1,2}  # 创建一个新的集合
s10
{1, 2}
s10.issubset(s5)  # s10是s5的子集
True
s5.issuperset(s10)  #  s5是s10的超集
True
s9
{7, 8, 9, 'e', 'go', 'h', 'javascript', 'l', 'o'}
s9.issubset(s5)  # 很显然s9不是s5的子集
False

intersection-交集

求两个集合的交集,使用intersection函数或者&

print(s5)
print(s10)
{1, 2, 3, 4}
{1, 2}
s5.intersection(s10)
{1, 2}
s5 & s10
{1, 2}

union-并集

使用函数union或者|来表示两个集合的并集,会生成一个新的对象

print(s5)
print(s9)
{1, 2, 3, 4}
{'javascript', 'o', 7, 'l', 'go', 'h', 8, 9, 'e'}
s11 = s5|s9
s11
{1, 2, 3, 4, 7, 8, 9, 'e', 'go', 'h', 'javascript', 'l', 'o'}
s5.union(s9)
{1, 2, 3, 4, 7, 8, 9, 'e', 'go', 'h', 'javascript', 'l', 'o'}

difference-差集、补集

使用函数difference或者减号-

print(s5)
print(s10)
{1, 2, 3, 4}
{1, 2}
s5 - s10
{3, 4}
s5.difference(s10)
{3, 4}
s10 - s5
set()

symmetric_difference-对称差集

使用函数symmetric_difference或者symmetric_difference_update(原地更新数据)

s12 = {1,3,4,5,7}
s12
{1, 3, 4, 5, 7}
s5  # 原数据
{1, 2, 3, 4}
s5.symmetric_difference(s12)
{2, 5, 7}
s5  #  原数据没有改变
{1, 2, 3, 4}
s5.symmetric_difference_update(s12) 
s5    # 原数据为输出结果
{2, 5, 7}


如有文章对你有帮助,

在看”和转发是对我最大的支持!



关注Python极客专栏



Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/122354
 
450 次点击