跟老齐学Python之集合(set)


Posted in Python onSeptember 24, 2014

回顾一下已经了解的数据类型:int/str/bool/list/dict/tuple

还真的不少了.

不过,python是一个发展的语言,没准以后还出别的呢.看官可能有疑问了,出了这么多的数据类型,我也记不住呀,特别是里面还有不少方法.

不要担心记不住,你只要记住爱因斯坦说的就好了.

爱因斯坦在美国演讲,有人问:“你可记得声音的速度是多少?你如何记下许多东西?”
爱因斯坦轻松答道:“声音的速度是多少,我必须查辞典才能回答。因为我从来不记在辞典上已经印着的东西,我的记忆力是用来记忆书本上没有的东西。”

多么霸气的回答,这回答不仅仅霸气,更是在告诉我们一种方法:只要能够通过某种方法查找到的,就不需要记忆.

那么,上面那么多数据类型的各种方法,都不需要记忆了,因为它们都可以通过下述方法但不限于这些方法查到(这句话的逻辑还是比较严密的,包括但不限于...)

交互模式下用dir()或者help()
google(不推荐Xdu,原因自己体会啦)

为了能够在总体上对已经学习过的数据类型有了解,我们不妨做如下分类:

1.是否为序列类型:即该数据的元素是否能够索引.其中序列类型的包括str/list/tuple
2.是否可以原处修改:即该数据的元素是否能够原处修改(特别提醒看官,这里说的是原处修改问题,有的资料里面说str不能修改,也是指原处修改问题.为了避免误解,特别强调了原处).能够原处修改的是list/dict(特别说明,dict的键必须是不可修改的,dict的值可原处修改)
什么原处修改?看官能不能在交互模式下通过实例解释一下?

到这里,看官可千万不要以为本讲是复习课.本讲的主要内容不是复习,主要内容是要向看官介绍一种新的数据类型:集合(set).彻底晕倒了,到底python有多少个数据类型呢?又多出来了一个.

从基本道理上说,python中的数据类型可以很多,因为每个人都可以自己定义一种数据类型.但是,python官方认可或者说内置的数据类型,就那么几种了.基本上今天的set讲完,就差不多了.在以后的开发过程中,包括今天和以往介绍的数据类型,是常用的.当然,自己定义一个也可以,但是用原生的更好.

创建set

tuple算是list和str的杂合(杂交的都有自己的优势,上一节的末后已经显示了),那么set则可以堪称是list和dict的杂合.

set拥有类似dict的特点:可以用{}花括号来定义;其中的元素没有序列,也就是是非序列类型的数据;而且,set中的元素不可重复,这就类似dict的键.

set也有继承了一点list的特点:如可以原处修改(事实上是一种类别的set可以原处修改,另外一种不可以).

下面通过实验,进一步理解创建set的方法:

>>> s1 = set("qiwsir") #把str中的字符拆解开,形成set.特别注意观察:qiwsir中有两个i
>>> s1         #但是在s1中,只有一个i,也就是不能重复
set(['q', 'i', 's', 'r', 'w'])

>>> s2 = set([123,"google","face","book","facebook","book"])  #通过list创建set.不能有重复,元素可以是int/str
>>> s2
set(['facebook', 123, 'google', 'book', 'face'])        #元素顺序排列不是按照指定顺序

>>> s3 = {"facebook",123}    #通过{}直接创建
>>> s3
set([123, 'facebook'])

再大胆做几个探究,请看官注意观察结果:

>>> s3 = {"facebook",[1,2,'a'],{"name":"python","lang":"english"},123}
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'

>>> s3 = {"facebook",[1,2],123}
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

从上述实验中,可以看出,通过{}无法创建含有list/dict元素的set.

继续探索一个情况:

>>> s1
set(['q', 'i', 's', 'r', 'w'])
>>> s1[1] = "I"
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: 'set' object does not support item assignment

>>> s1   
set(['q', 'i', 's', 'r', 'w'])
>>> lst = list(s1)
>>> lst
['q', 'i', 's', 'r', 'w']
>>> lst[1] = "I"
>>> lst
['q', 'I', 's', 'r', 'w']

上面的探索中,将set和list做了一个对比,虽然说两者都能够做原处修改,但是,通过索引编号(偏移量)的方式,直接修改,list允许,但是set报错.

那么,set如何修改呢?

更改set

还是用前面已经介绍过多次的自学方法,把set的有关内置函数找出来,看看都可以对set做什么操作.

>>> dir(set)
['__and__', '__class__', '__cmp__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__iand__', '__init__', '__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', 'clear', 'copy', 'difference', 'difference_update', 'discard', 'intersection', 'intersection_update', 'isdisjoint', 'issubset', 'issuperset', 'pop', 'remove', 'symmetric_difference', 'symmetric_difference_update', 'union', 'update'

然后用help()可以找到每个函数的具体使用方法,下面列几个例子:

增加元素

>>> help(set.add)

Help on method_descriptor:

add(...)
Add an element to a set. 
This has no effect if the element is already present.

下面在交互模式这个最好的实验室里面做实验:

>>> a_set = {}       #我想当然地认为这样也可以建立一个set
>>> a_set.add("qiwsir")   #报错.看看错误信息,居然告诉我dict没有add.我分明建立的是set呀.
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
AttributeError: 'dict' object has no attribute 'add'
>>> type(a_set)       #type之后发现,计算机认为我建立的是一个dict   
<type 'dict'>

特别说明一下,{}这个东西,在dict和set中都用.但是,如上面的方法建立的是dict,不是set.这是python规定的.要建立set,只能用前面介绍的方法了.

>>> a_set = {'a','i'}    #这回就是set了吧
>>> type(a_set)
 <type 'set'>       #果然

>>> a_set.add("qiwsir")   #增加一个元素
>>> a_set          #原处修改,即原来的a_set引用对象已经改变
set(['i', 'a', 'qiwsir'])

>>> b_set = set("python")
>>> type(b_set)
<type 'set'>
>>> b_set
set(['h', 'o', 'n', 'p', 't', 'y'])
>>> b_set.add("qiwsir")
>>> b_set
set(['h', 'o', 'n', 'p', 't', 'qiwsir', 'y'])

>>> b_set.add([1,2,3])   #这样做是不行滴,跟前面一样,报错.
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

>>> b_set.add('[1,2,3]')  #可以这样!
>>> b_set
set(['[1,2,3]', 'h', 'o', 'n', 'p', 't', 'qiwsir', 'y'])

除了上面的增加元素方法之外,还能够从另外一个set中合并过来元素,方法是set.update(s2)

>>> help(set.update)
update(...)
  Update a set with the union of itself and others.

>>> s1
set(['a', 'b'])
>>> s2
set(['github', 'qiwsir'])
>>> s1.update(s2)    #把s2的元素并入到s1中.
>>> s1         #s1的引用对象修改
set(['a', 'qiwsir', 'b', 'github'])
>>> s2         #s2的未变
set(['github', 'qiwsir'])

删除

>>> help(set.pop)
pop(...)
  Remove and return an arbitrary set element.
  Raises KeyError if the set is empty.

>>> b_set
set(['[1,2,3]', 'h', 'o', 'n', 'p', 't', 'qiwsir', 'y'])
>>> b_set.pop()   #从set中任意选一个删除,并返回该值
'[1,2,3]'
>>> b_set.pop()
'h'
>>> b_set.pop()
'o'
>>> b_set
set(['n', 'p', 't', 'qiwsir', 'y'])

>>> b_set.pop("n") #如果要指定删除某个元素,报错了.
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: pop() takes no arguments (1 given)

set.pop()是从set中任意选一个元素,删除并将这个值返回.但是,不能指定删除某个元素.报错信息中就告诉我们了,pop()不能有参数.此外,如果set是空的了,也报错.这条是帮助信息告诉我们的,看官可以试试.

要删除指定的元素,怎么办?

>>> help(set.remove)

remove(...)
  Remove an element from a set; it must be a member.  

  If the element is not a member, raise a KeyError.
set.remove(obj)中的obj,必须是set中的元素,否则就报错.试一试:

>>> a_set
set(['i', 'a', 'qiwsir'])
>>> a_set.remove("i")
>>> a_set
set(['a', 'qiwsir'])
>>> a_set.remove("w")
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
KeyError: 'w'

跟remove(obj)类似的还有一个discard(obj):

>>> help(set.discard)

discard(...)
    Remove an element from a set if it is a member.

    If the element is not a member, do nothing.
与help(set.remove)的信息对比,看看有什么不同.discard(obj)中的obj如果是set中的元素,就删除,如果不是,就什么也不做,do nothing.新闻就要对比着看才有意思呢.这里也一样.

>>> a_set.discard('a')
>>> a_set    
set(['qiwsir'])
>>> a_set.discard('b')
>>>

在删除上还有一个绝杀,就是set.clear(),它的功能是:Remove all elements from this set.(看官自己在交互模式下help(set.clear))

>>> a_set
set(['qiwsir'])
>>> a_set.clear()
>>> a_set
set([])
>>> bool(a_set)   #空了,bool一下返回False.
False

知识

集合,也是一个数学概念(以下定义来自维基百科)

集合(或简称集)是基本的数学概念,它是集合论的研究对象。最简单的说法,即是在最原始的集合论─朴素集合论─中的定义,集合就是“一堆东西”。集合里的“东西”,叫作元素。若然 x 是集合 A 的元素,记作 x ∈ A。

集合是现代数学中一个重要的基本概念。集合论的基本理论直到十九世纪末才被创立,现在已经是数学教育中一个普遍存在的部分,在小学时就开始学习了。这里对被数学家们称为“直观的”或“朴素的”集合论进行一个简短而基本的介绍;更详细的分析可见朴素集合论。对集合进行严格的公理推导可见公理化集合论。

在计算机中,集合是什么呢?同样来自维基百科,这么说的:

在计算机科学中,集合是一组可变数量的数据项(也可能是0个)的组合,这些数据项可能共享某些特征,需要以某种操作方式一起进行操作。一般来讲,这些数据项的类型是相同的,或基类相同(若使用的语言支持继承)。列表(或数组)通常不被认为是集合,因为其大小固定,但事实上它常常在实现中作为某些形式的集合使用。
集合的种类包括列表,集,多重集,树和图。枚举类型可以是列表或集。

不管是否明白,貌似很厉害呀.

是的,所以本讲仅仅是对集合有一个入门.关于集合的更多操作如运算/比较等,还没有涉及呢.

Python 相关文章推荐
Python urllib、urllib2、httplib抓取网页代码实例
May 09 Python
python字符串的常用操作方法小结
May 21 Python
Python实现基于多线程、多用户的FTP服务器与客户端功能完整实例
Aug 18 Python
Python 模拟购物车的实例讲解
Sep 11 Python
利用python将pdf输出为txt的实例讲解
Apr 23 Python
用Python一键搭建Http服务器的方法
Jun 01 Python
Python中staticmethod和classmethod的作用与区别
Oct 11 Python
Python 访问限制 private public的详细介绍
Oct 16 Python
python画图常规设置方式
Mar 05 Python
Python代码需要缩进吗
Jul 01 Python
Python3爬虫带上cookie的实例代码
Jul 28 Python
Python为何不支持switch语句原理详解
Oct 21 Python
跟老齐学Python之有点简约的元组
Sep 24 #Python
跟老齐学Python之dict()的操作方法
Sep 24 #Python
Python单链表的简单实现方法
Sep 23 #Python
Python中bisect的用法
Sep 23 #Python
python元组操作实例解析
Sep 23 #Python
Python中实现两个字典(dict)合并的方法
Sep 23 #Python
python实现去除下载电影和电视剧文件名中的多余字符的方法
Sep 23 #Python
You might like
Protoss兵种介绍
2020/03/14 星际争霸
php读取大文件示例分享(文件操作类)
2014/04/13 PHP
php使用cookie实现记住用户名和密码实现代码
2015/04/27 PHP
Linux操作系统安装LAMP环境
2015/06/26 PHP
超级兔子让浮动层消失的前因后果
2007/03/09 Javascript
ExtJS GridPanel 根据条件改变字体颜色
2010/03/08 Javascript
遨游,飞飞,IE,空中网 浏览器无提示关闭方法
2011/07/11 Javascript
基于jquery实现的定时显示与隐藏div广告的实现代码
2013/08/22 Javascript
window.print打印指定div实例代码
2013/12/13 Javascript
jQuery判断元素是否存在的可靠方法
2014/05/06 Javascript
javascript的事件触发器介绍的实现
2014/06/05 Javascript
jquery实现在页面加载完毕后获取图片高度或宽度
2014/06/16 Javascript
JS实现窗口加载时模拟鼠标移动的方法
2015/06/03 Javascript
JavaScript原生xmlHttp与jquery的ajax方法json数据格式实例
2015/12/04 Javascript
jQuery模仿单选按钮选中效果
2016/06/24 Javascript
浅析JS中对函数function的理解(基础篇)
2016/10/14 Javascript
jQuery实现模拟flash头像裁切上传功能示例
2016/12/11 Javascript
JavaScript 输出显示内容(document.write、alert、innerHTML、console.log)
2016/12/14 Javascript
浅谈手写node可读流之流动模式
2018/06/01 Javascript
[01:04:14]OG vs Winstrike 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
[52:40]完美世界DOTA2联赛PWL S2 Magma vs GXR 第一场 11.29
2020/12/02 DOTA
python比较两个列表大小的方法
2015/07/11 Python
python中map()与zip()操作方法
2016/02/27 Python
[原创]pip和pygal的安装实例教程
2017/12/07 Python
解决nohup重定向python输出到文件不成功的问题
2018/05/11 Python
python简单验证码识别的实现方法
2019/05/10 Python
Python获取一个用户名的组ID过程解析
2019/09/03 Python
python实现将列表中各个值快速赋值给多个变量
2020/04/02 Python
Python中socket网络通信是干嘛的
2020/05/27 Python
技校教师求职简历的自我评价
2013/10/20 职场文书
毕业留言寄语大全
2014/04/10 职场文书
2015年挂职锻炼工作总结
2014/12/12 职场文书
综合素质评价个性与发展自我评价
2015/03/06 职场文书
小学六一儿童节活动开幕词
2016/03/04 职场文书
Nginx内网单机反向代理的实现
2021/11/07 Servers
国际最新研究在陨石中发现DNA主要成分 或由陨石带来地球
2022/04/29 数码科技