回顧一下已經學過的數據類型: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個)的組合,這些數據項可能共享某些特征,需要以某種操作方式一起進行操作。一般來講,這些數據項的類型是相同的,或基類相同(若使用的語言支持繼承)。列表(或數組)通常不被認為是集合,因為其大小固定,但事實上它常常在實現中作為某些形式的集合使用。
>
> 集合的種類包括列表,集,多重集,樹和圖。枚舉類型可以是列表或集。
不管是否明白,貌似很厲害呀.
是的,所以本講僅僅是對集合有一個入門.關于集合的更多操作如運算/比較等,還沒有涉及呢.
- 第零章 預備
- 關于Python的故事
- 從小工到專家
- Python安裝
- 集成開發環境
- 第壹章 基本數據類型
- 數和四則運算
- 除法
- 常用數學函數和運算優先級
- 寫一個簡單的程序
- 字符串(1)
- 字符串(2)
- 字符串(3)
- 字符串(4)
- 字符編碼
- 列表(1)
- 列表(2)
- 列表(3)
- 回顧list和str
- 元組
- 字典(1)
- 字典(2)
- 集合(1)
- 集合(2)
- 第貳章 語句和文件
- 運算符
- 語句(1)
- 語句(2)
- 語句(3)
- 語句(4)
- 語句(5)
- 文件(1)
- 文件(2)
- 迭代
- 練習
- 自省
- 第叁章 函數
- 函數(1)
- 函數(2)
- 函數(3)
- 函數(4)
- 函數練習
- 第肆章 類
- 類(1)
- 類(2)
- 類(3)
- 類(4)
- 類(5)
- 多態和封裝
- 特殊方法(1)
- 特殊方法(2)
- 迭代器
- 生成器
- 上下文管理器
- 第伍章 錯誤和異常
- 錯誤和異常(1)
- 錯誤和異常(2)
- 錯誤和異常(3)
- 第陸章 模塊
- 編寫模塊
- 標準庫(1)
- 標準庫(2)
- 標準庫(3)
- 標準庫(4)
- 標準庫(5)
- 標準庫(6)
- 標準庫(7)
- 標準庫(8)
- 第三方庫
- 第柒章 保存數據
- 將數據存入文件
- mysql數據庫(1)
- MySQL數據庫(2)
- mongodb數據庫(1)
- SQLite數據庫
- 電子表格
- 第捌章 用Tornado做網站
- 為做網站而準備
- 分析Hello
- 用tornado做網站(1)
- 用tornado做網站(2)
- 用tornado做網站(3)
- 用tornado做網站(4)
- 用tornado做網站(5)
- 用tornado做網站(6)
- 用tornado做網站(7)
- 第玖章 科學計算
- 為計算做準備
- Pandas使用(1)
- Pandas使用(2)
- 處理股票數據
- 附:網絡文摘
- 如何成為Python高手
- ASCII、Unicode、GBK和UTF-8字符編碼的區別聯系