ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
回顾一下已经学过的数据类型:int/str/bool/list/dict/tuple 还真的不少了. 不过,python是一个发展的语言,没准以后还出别的呢.看官可能有疑问了,出了这么多的数据类型,我也记不住呀,特别是里面还有不少方法. 不要担心记不住,你只要记住爱因斯坦说的就好了. > 爱因斯坦在美国演讲,有人问:“你可记得声音的速度是多少?你如何记下许多东西?” > > 爱因斯坦轻松答道:“声音的速度是多少,我必须查辞典才能回答。因为我从来不记在辞典上已经印着的东西,我的记忆力是用来记忆书本上没有的东西。” 多么霸气的回答,这回答不仅仅霸气,更告诉我们一种方法:只要能够通过某种方法查找到的,就不需要记忆. 那么,上面那么多数据类型及其各种方法,都不需要记忆了,因为它们都可以通过下述方法但不限于这些方法查到(这句话的逻辑还是比较严密的,包括但不限于...) * 交互模式下用dir()或者help() * google(不推荐Xdu,原因自己体会啦) 在已经学过的数据类型中: * 能够索引的,如list/str,其中的元素可以重复 * 可变的,如list/dict,即其中的元素/键值对可以原地修改 * 不可变的,如str/int,即不能进行原地修改 * 无索引序列的,如dict,即其中的元素(键值对)没有排列顺序 现在要介绍另外一种类型的数据,英文是set,翻译过来叫做“集合”。它的特点是:有的可变,有的不可变;元素无次序,不可重复。 ## [](https://github.com/qiwsir/StarterLearningPython/blob/master/118.md#创建set)创建set tuple算是list和str的杂合(杂交的都有自己的优势,上一节的末后已经显示了),那么set则可以堪称是list和dict的杂合. set拥有类似dict的特点:可以用{}花括号来定义;其中的元素没有序列,也就是是非序列类型的数据;而且,set中的元素不可重复,这就类似dict的键. set也有一点list的特点:有一种集合可以原处修改. 下面通过实验,进一步理解创建set的方法: ~~~ >>> s1 = set("qiwsir") >>> s1 set(['q', 'i', 's', 'r', 'w']) ~~~ 把str中的字符拆解开,形成set.特别注意观察:qiwsir中有两个i,但是在s1中,只有一个i,也就是集合中元素不能重复。 ~~~ >>> s2 = set([123,"google","face","book","facebook","book"]) >>> s2 set(['facebook', 123, 'google', 'book', 'face']) ~~~ 在创建集合的时候,如果发现了重复的元素,就会过滤一下,剩下不重复的。而且,从s2的创建可以看出,查看结果是显示的元素顺序排列与开始建立是不同,完全是随意显示的,这说明集合中的元素没有序列。 ~~~ >>> s3 = {"facebook",123} #通过{}直接创建 >>> s3 set([123, 'facebook']) ~~~ 除了用`set()`来创建集合。还可以使用`{}`的方式,但是这种方式不提倡使用,因为在某些情况下,python搞不清楚是字典还是集合。看看下面的探讨就发现问题了。 ~~~ >>> 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. 认真阅读报错信息,有这样的词汇:“unhashable”,在理解这个词之前,先看它的反义词“hashable”,很多时候翻译为“可哈希”,其实它有一个不是音译的名词“散列”,这个在[《字典(1)》](https://github.com/qiwsir/StarterLearningPython/blob/master/116.md)中有说明。网上搜一下,有不少文章对这个进行诠释。如果我们简单点理解,某数据“不可哈希”(unhashable)就是其可变,如list/dict,都能原地修改,就是unhashable。否则,不可变的,类似str那样不能原地修改,就是hashable(可哈希)的。 对于前面已经提到的字典,其键必须是hashable数据,即不可变的。 现在遇到的集合,其元素也要是“可哈希”的。上面例子中,试图将字典、列表作为元素的元素,就报错了。而且报错信息中明确告知list/dict是不可哈希类型,言外之意,里面的元素都应该是可哈希类型。 继续探索一个情况: ~~~ >>> 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'] ~~~ 分别用`list()`和`set()`能够实现两种数据类型之间的转化。 特别说明,利用`set()`建立起来的集合是可变集合,可变集合都是unhashable类型的。 ## [](https://github.com/qiwsir/StarterLearningPython/blob/master/118.md#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()可以找到每个函数的具体使用方法,下面列几个例子: ### [](https://github.com/qiwsir/StarterLearningPython/blob/master/118.md#add-update)add, update ~~~ >>> 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]) #报错.list是不可哈希的,集合中的元素应该是hashable类型。 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']) ~~~ ### [](https://github.com/qiwsir/StarterLearningPython/blob/master/118.md#pop-remove-discard-clear)pop, remove, discard, clear ~~~ >>> 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 ~~~ ## [](https://github.com/qiwsir/StarterLearningPython/blob/master/118.md#知识)知识 集合,也是一个数学概念(以下定义来自[维基百科](http://zh.wikipedia.org/wiki/%E9%9B%86%E5%90%88_%28%E6%95%B0%E5%AD%A6%29)) > 集合(或简称集)是基本的数学概念,它是集合论的研究对象。最简单的说法,即是在最原始的集合论─朴素集合论─中的定义,集合就是“一堆东西”。集合里的“东西”,叫作元素。若然 x 是集合 A 的元素,记作 x ∈ A。 > > 集合是现代数学中一个重要的基本概念。集合论的基本理论直到十九世纪末才被创立,现在已经是数学教育中一个普遍存在的部分,在小学时就开始学习了。这里对被数学家们称为“直观的”或“朴素的”集合论进行一个简短而基本的介绍;更详细的分析可见朴素集合论。对集合进行严格的公理推导可见公理化集合论。 在计算机中,集合是什么呢?同样来自[维基百科](http://zh.wikipedia.org/wiki/%E9%9B%86%E5%90%88_%28%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%A7%91%E5%AD%A6%29),这么说的: > 在计算机科学中,集合是一组可变数量的数据项(也可能是0个)的组合,这些数据项可能共享某些特征,需要以某种操作方式一起进行操作。一般来讲,这些数据项的类型是相同的,或基类相同(若使用的语言支持继承)。列表(或数组)通常不被认为是集合,因为其大小固定,但事实上它常常在实现中作为某些形式的集合使用。 > > 集合的种类包括列表,集,多重集,树和图。枚举类型可以是列表或集。 不管是否明白,貌似很厉害呀. 是的,所以本讲仅仅是对集合有一个入门.关于集合的更多操作如运算/比较等,还没有涉及呢.