22
33#集合(1)
44
5- 回顾一下已经学过的数据类型 : int /str/bool/list/dict/tuple
5+ 已经学习了几种对象类型。
66
7- 还真的不少了.
7+ 温故而知新。它们是:int/float/str/bool/list/dict/tuple
88
9- 不过,python是一个发展的语言,没准以后还出别的呢.看官可能有疑问了,出了这么多的数据类型,我也记不住呀,特别是里面还有不少方法.
9+ 还真的不少了。
1010
11- 不要担心记不住,你只要记住爱因斯坦说的就好了.
11+ 不过,Python是一个发展的语言,没准以后还出别的呢。
12+
13+ 读者可能有疑问了,出了这么多的类型,我也记不住呀,特别是里面还有不少方法。
14+
15+ 不要担心记不住,你只要记住爱因斯坦说的就好了。
1216
1317> 爱因斯坦在美国演讲,有人问:“你可记得声音的速度是多少?你如何记下许多东西?”
1418
1519> 爱因斯坦轻松答道:“声音的速度是多少,我必须查辞典才能回答。因为我从来不记在辞典上已经印着的东西,我的记忆力是用来记忆书本上没有的东西。”
1620
17- 多么霸气的回答,这回答不仅仅霸气,更告诉我们一种方法:只要能够通过某种方法查找到的,就不需要记忆.
21+ 多么霸气的回答。
1822
19- 那么,上面那么多数据类型及其各种方法,都不需要记忆了,因为它们都可以通过下述方法但不限于这些方法查到(这句话的逻辑还是比较严密的,包括但不限于...)
23+ 这回答不仅仅霸气,更告诉我们一种方法:只要能够通过某种方法查找到的,就不需要记忆。
24+
25+ 所以,再多的数据类型及其各种方法,都不需要记忆。因为它们都可以通过下述方法但不限于这些方法查到(这句话的逻辑还是比较严密的,包括但不限于...)
2026
2127- 交互模式下用dir()或者help()
2228- google(不推荐Xdu,原因自己体会啦)
2329
24- 在已经学过的数据类型中:
30+ 还有,如果你经常练习,会发现很多东西自然而然就记住了。
31+
32+ 在已经学过的不同种类型的对象中:
2533
2634- 能够索引的,如list/str,其中的元素可以重复
2735- 可变的,如list/dict,即其中的元素/键值对可以原地修改
3038
3139现在要介绍另外一种类型的数据,英文是set,翻译过来叫做“集合”。它的特点是:有的可变,有的不可变;元素无次序,不可重复。
3240
33- ##创建set
41+ ##创建集合
3442
35- tuple算是list和str的杂合 (杂交的都有自己的优势,上一节的末后已经显示了),那么set则可以堪称是list和dict的杂合 .
43+ 元组算是列表和字符串的某些特征的杂合 (杂交的都有自己的优势,上一节的末后已经显示了),那么集合则可以堪称是列表和字典的某些特征杂合 .
3644
37- set拥有类似dict的特点:可以用{}花括号来定义;其中的元素没有序列,也就是是非序列类型的数据;而且,set中的元素不可重复,这就类似dict的键.
45+ 请读者细细品味,这种杂合的特征。
3846
39- set也有一点list的特点:有一种集合可以原处修改.
40-
41- 下面通过实验,进一步理解创建set的方法:
47+ 首先要创建集合,其方法是:
4248
4349 >>> s1 = set("qiwsir")
4450 >>> s1
4551 set(['q', 'i', 's', 'r', 'w'])
4652
47- 把str中的字符拆解开,形成set.特别注意观察: qiwsir 中有两个i,但是在s1中,只有一个i,也就是集合中元素不能重复。
53+ 把字符串中的字符拆解开,形成集合。
54+
55+ 特别注意观察,` qiwsir ` 中有两个` i ` ,但是在集合中,只有一个` i ` ,也就是集合中元素不能重复。
4856
4957 >>> s2 = set([123,"google","face","book","facebook","book"])
5058 >>> s2
5159 set(['facebook', 123, 'google', 'book', 'face'])
5260
53- 在创建集合的时候,如果发现了重复的元素,就会过滤一下,剩下不重复的。而且,从s2的创建可以看出,查看结果是显示的元素顺序排列与开始建立是不同,完全是随意显示的,这说明集合中的元素没有序列。
61+ 在创建集合的时候,如果发现了重复的元素,就会过滤掉,剩下不重复的。
62+
63+ 在使用` dir() ` 来看看集合的方法,特别从下面找一找有没有` index ` ,如果有它,就说明可以索引,否则,集合就没有索引。
64+
65+ >>> dir(set)
66+ ['__and__', '__class__', '__contains__', '__delattr__', '__dir__', '__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']
67+
68+ 请用你那双慧眼,寻找一番。
69+
70+ 没有` index ` 。
71+
72+ 的确没有。所以,集合没有索引,也就没有顺序而言,它不属序列。当你这样操作的时候,
73+
74+ >>> s1 = set(['q', 'i', 's', 'r', 'w'])
75+ >>> s1[1]
76+ Traceback (most recent call last):
77+ File "<pyshell#10>", line 1, in <module>
78+ s1[1]
79+ TypeError: 'set' object does not support indexing
80+
81+ 报错。并且明确告知我们,不支持索引。
82+
83+ 除了用` set() ` 来创建集合。还可以使用` {} ` 的方式。
5484
5585 >>> s3 = {"facebook",123} #通过{}直接创建
5686 >>> s3
5787 set([123, 'facebook'])
5888
59- 除了用 ` set() ` 来创建集合。还可以使用 ` {} ` 的方式,但是这种方式不提倡使用,因为在某些情况下,python搞不清楚是字典还是集合。看看下面的探讨就发现问题了 。
89+ 但是这种方式不提倡使用。因为我们已经将 ` {} ` 常常用在字典上了,要避免歧义才好 。
6090
61- >>> s3 = {"facebook",[1,2,'a'],{"name":"python","lang":"english"},123}
91+ 看看下面的探讨就发现问题了。
92+
93+ >>> s3 = {"facebook", [1,2,'a'], {"name":"python","lang":"english"}, 123}
6294 Traceback (most recent call last):
6395 File "<stdin>", line 1, in <module>
6496 TypeError: unhashable type: 'dict'
6597
66- >>> s3 = {"facebook",[1,2],123}
98+ >>> s3 = {"facebook", [1,2], 123}
6799 Traceback (most recent call last):
68100 File "<stdin>", line 1, in <module>
69101 TypeError: unhashable type: 'list'
70102
71- 从上述实验中,可以看出,通过{}无法创建含有list/dict元素的set.
72-
73- 认真阅读报错信息,有这样的词汇:“unhashable”,在理解这个词之前,先看它的反义词“hashable”,很多时候翻译为“可哈希”,其实它有一个不是音译的名词“散列”,这个在[ 《字典(1)》] ( ./116.md ) 中有说明。网上搜一下,有不少文章对这个进行诠释。如果我们简单点理解,某数据“不可哈希”(unhashable)就是其可变,如list/dict,都能原地修改,就是unhashable。否则,不可变的,类似str那样不能原地修改,就是hashable(可哈希)的。
103+ 认真阅读报错信息,有这样的词汇:“unhashable”,在理解这个词之前,先看它的反义词“hashable”,翻译为“可哈希”。网上搜一下,有不少文章对这个进行诠释。如果我们简单点理解,某数据“不可哈希”(unhashable)就是其可变,如list/dict,都能原地修改,就是unhashable。否则,不可变的,类似字符串那样不能原地修改,就是hashable(可哈希)的。
74104
75105对于前面已经提到的字典,其键必须是hashable数据,即不可变的。
76106
77- 现在遇到的集合,其元素也要是“可哈希”的。上面例子中,试图将字典、列表作为元素的元素,就报错了。而且报错信息中明确告知list/dict是不可哈希类型,言外之意,里面的元素都应该是可哈希类型。
78-
79- 继续探索一个情况:
80-
81- >>> s1
82- set(['q', 'i', 's', 'r', 'w'])
83- >>> s1[1] = "I"
84- Traceback (most recent call last):
85- File "<stdin>", line 1, in <module>
86- TypeError: 'set' object does not support item assignment
87-
88- 这里报错,进一步说明集合没有序列,不能用索引方式对其进行修改。
107+ 现在遇到的集合,其元素也要是“可哈希”的。上面例子中,试图将字典、列表作为元素的元素,就报错了。而且报错信息中明确告知列表、字典是不可哈希类型,言外之意,里面的元素都应该是可哈希类型。
89108
90- >>> s1
91- set([ 'q', 'i', 's', 'r', 'w'] )
92- >>> lst = list(s1)
93- >>> lst
94- [ 'q', 'i', 's', 'r', 'w']
95- >>> lst[ 1] = "I"
96- >>> lst
97- [ 'q', 'I', 's', 'r', 'w']
98-
99- 分别用` list() ` 和` set() ` 能够实现两种数据类型之间的转化。
100-
101109特别说明,利用` set() ` 建立起来的集合是可变集合,可变集合都是unhashable类型的。
102110
103111##set的方法
104112
105- 还是用前面已经介绍过多次的自学方法,把set的有关内置函数找出来,看看都可以对set做什么操作.
113+ 从前面的 ` dir(set) ` 结果中,你可以看到不少集合的方法。
106114
107- >>> dir(set)
108- ['__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']
109-
110- 为了看的清楚,我把双划线__ 开始的先删除掉(后面我们会有专题讲述这些):
115+ 为了看的清楚,我把双划线` __ ` 开始的先删除掉,剩下的就是:
111116
112117> 'add', 'clear', 'copy', 'difference', 'difference_update', 'discard', 'intersection', 'intersection_update', 'isdisjoint', 'issubset', 'issuperset', 'pop', 'remove', 'symmetric_difference', 'symmetric_difference_update', 'union', 'update'
113118
114- 然后用help()可以找到每个函数的具体使用方法,下面列几个例子:
119+ 然后用help()可以找到每个函数的具体使用方法。读者完全可以用这种方法自己查看了。
120+
121+ 下面列几个例子。
115122
116123###add, update
117124
@@ -123,7 +130,7 @@ set也有一点list的特点:有一种集合可以原处修改.
123130 Add an element to a set.
124131 This has no effect if the element is already present.
125132
126- 下面在交互模式这个最好的实验室里面做实验 :
133+ 在交互模式这个最好的实验室里面做实验 :
127134
128135 >>> a_set = {} #我想当然地认为这样也可以建立一个set
129136 >>> a_set.add("qiwsir") #报错.看看错误信息,居然告诉我dict没有add.我分明建立的是set呀.
@@ -133,16 +140,33 @@ set也有一点list的特点:有一种集合可以原处修改.
133140 >>> type(a_set) #type之后发现,计算机认为我建立的是一个dict
134141 <type 'dict'>
135142
136- 特别说明一下,{}这个东西,在dict和set中都用.但是,如上面的方法建立的是dict,不是set.这是python规定的.要建立set,只能用前面介绍的方法了.
143+ 特别说明一下,` {} ` 这个东西,在字典和集合中都用.但是,如上面的方法建立的是字典,不是集合.
144+
145+ 这是python规定的.
146+
147+ 要建立空集合,不得不使用` set() ` 。
148+
149+ >>> s = set()
150+ >>> type(s)
151+ <class 'set'> #Python 2的返回结果略有差异,为<type 'set'>
152+
153+ 当然,非空集合,依然可以这样:
137154
138155 >>> a_set = {'a','i'} #这回就是set了吧
139156 >>> type(a_set)
140- <type 'set'> #果然
157+ <type 'set'> #Python 3返回: <class 'set'>
158+
159+ 然后就开始对这个集合使用` add() ` 方法,并看效果。
141160
142161 >>> a_set.add("qiwsir") #增加一个元素
143- >>> a_set #原处修改,即原来的a_set引用对象已经改变
162+
163+ 没有报错,就意味着成功。没有返回值,根据我们经验,这属于“原地修改”。
164+
165+ >>> a_set
144166 set(['i', 'a', 'qiwsir'])
145-
167+
168+ 这次经验胜利了。继续洋洋得意地敲代码。
169+
146170 >>> b_set = set("python")
147171 >>> type(b_set)
148172 <type 'set'>
@@ -151,30 +175,38 @@ set也有一点list的特点:有一种集合可以原处修改.
151175 >>> b_set.add("qiwsir")
152176 >>> b_set
153177 set(['h', 'o', 'n', 'p', 't', 'qiwsir', 'y'])
178+
179+ 成功继续伴随着。废话!仅仅是刚才的重复罢了。重复是必须的,这样是为了加深印象。
154180
155- >>> b_set.add([1,2,3]) #报错.list是不可哈希的,集合中的元素应该是hashable类型。
181+ >>> b_set.add([ 1,2,3] )
156182 Traceback (most recent call last):
157183 File "<stdin >", line 1, in <module >
158184 TypeError: unhashable type: 'list'
159185
160- >>> b_set.add('[1,2,3]') #可以这样!
186+ 报错。哪里错了?
187+
188+ 遇见错误,不要沮丧。认真阅读报错信息:列表是不可哈希的。洋洋得意中忘记前面强调的:“集合中的元素应该是hashable类型”。
189+
190+ 耍一个小聪明吧。
191+
192+ >>> b_set.add('[1,2,3]')
161193 >>> b_set
162194 set(['[1,2,3]', 'h', 'o', 'n', 'p', 't', 'qiwsir', 'y'])
163195
164- 除了上面的增加元素方法之外,还能够从另外一个set中合并过来元素,方法是set.update(s2)
196+ 为什么这么一搞就可以了呢?仔细观察,这回不是增加列表了,本质是字符串。
197+
198+ 除了上面的增加元素方法之外,还能够从另外一个集合中合并过来元素,方法是` set.update(s2) ` 。
165199
166200 >>> help(set.update)
167201 update(...)
168202 Update a set with the union of itself and others.
169203
170- >>> s1
171- set(['a', 'b'])
172- >>> s2
173- set(['github', 'qiwsir'])
204+ >>> s1 = set(['a', 'b'])
205+ >>> s2 = set(['github', 'qiwsir'])
174206 >>> s1.update(s2) #把s2的元素并入到s1中.
175- >>> s1 #s1的引用对象修改
207+ >>> s1 #s1的引用对象修改
176208 set(['a', 'qiwsir', 'b', 'github'])
177- >>> s2 #s2的未变
209+ >>> s2 #s2的未变
178210 set(['github', 'qiwsir'])
179211
180212如果仅仅是这样的操作,容易误以为` update ` 方法的参数只能是集合。非也。看文档中的描述,这个方法的作用是用原有的集合自身和其它的什么东西构成的新集合更新原来的集合。这句话有点长,可以多读一遍。分解开来,可以理解为:others是指的作为参数的不可变对象,将它和原来的集合组成新的集合,用这个新集合替代原来的集合。举例:
@@ -195,6 +227,8 @@ set也有一点list的特点:有一种集合可以原处修改.
195227 Remove and return an arbitrary set element.
196228 Raises KeyError if the set is empty.
197229
230+ 一下变量承接前面的操作,
231+
198232 >>> b_set
199233 set(['[1,2,3]', 'h', 'o', 'n', 'p', 't', 'qiwsir', 'y'])
200234 >>> b_set.pop() #从set中任意选一个删除,并返回该值
@@ -205,13 +239,19 @@ set也有一点list的特点:有一种集合可以原处修改.
205239 'o'
206240 >>> b_set
207241 set(['n', 'p', 't', 'qiwsir', 'y'])
242+
243+ 能不能指定删除某个元素?
208244
209- >>> b_set.pop("n") #如果要指定删除某个元素,报错了.
245+ >>> b_set.pop("n")
210246 Traceback (most recent call last):
211247 File "<stdin >", line 1, in <module >
212248 TypeError: pop() takes no arguments (1 given)
213249
214- set.pop()是从set中任意选一个元素,删除并将这个值返回.但是,不能指定删除某个元素.报错信息中就告诉我们了,pop()不能有参数.此外,如果set是空的了,也报错.这条是帮助信息告诉我们的,看官可以试试.
250+ set.pop()是从set中任意选一个元素,删除并将这个值返回。
251+
252+ 但是,不能指定删除某个元素。报错信息中就告诉我们了,` pop() ` 不能有参数。
253+
254+ 此外,如果集合已经是空的了,再删除,也报错。这条是帮助文档中告诉我们的,读者可以试试。
215255
216256要删除指定的元素,怎么办?
217257
@@ -234,7 +274,7 @@ set.pop()是从set中任意选一个元素,删除并将这个值返回.但是,
234274 File "<stdin>", line 1, in <module>
235275 KeyError: 'w'
236276
237- 跟remove (obj)类似的还有一个discard (obj):
277+ 跟 ` remove (obj)` 类似的还有一个 ` discard (obj)` :
238278
239279 >>> help(set.discard)
240280
@@ -243,15 +283,19 @@ set.pop()是从set中任意选一个元素,删除并将这个值返回.但是,
243283
244284 If the element is not a member, do nothing.
245285
246- 与` help(set.remove) ` 的信息对比,看看有什么不同.discard(obj)中的obj如果是set中的元素,就删除,如果不是,就什么也不做,do nothing.新闻就要对比着看才有意思呢.这里也一样.
286+ 与` help(set.remove) ` 的信息对比,看看有什么不同?
287+
288+ ` discard(obj) ` 中的` obj ` 如果是集合中的元素,就删除;如果不是,就什么也不做,do nothing。
289+
290+ 新闻就要对比着看才有意思呢。这里也一样.
247291
248292 >>> a_set.discard('a')
249293 >>> a_set
250294 set(['qiwsir'])
251295 >>> a_set.discard('b')
252296 >>>
253297
254- 在删除上还有一个绝杀,就是set .clear(),它的功能是: Remove all elements from this set.(看官自己在交互模式下help (set.clear))
298+ 在删除上还有一个绝杀,就是 ` set .clear()` ,它的功能是: Remove all elements from this set.(自己在交互模式下 ` help (set.clear)` )
255299
256300 >>> a_set
257301 set(['qiwsir'])
@@ -277,7 +321,7 @@ set.pop()是从set中任意选一个元素,删除并将这个值返回.但是,
277321
278322不管是否明白,貌似很厉害呀.
279323
280- 是的,所以本讲仅仅是对集合有一个入门.关于集合的更多操作如运算 /比较等,还没有涉及呢.
324+ 是的,所以本讲仅仅是对集合有一个入门.关于集合的更多操作,如运算 /比较等,还没有涉及呢.
281325
282326------
283327
0 commit comments