鍍金池/ 教程/ Python/ 集合(1)
標(biāo)準(zhǔn)庫 (4)
如何成為 Python 高手
標(biāo)準(zhǔn)庫 (6)
標(biāo)準(zhǔn)庫 (3)
類(2)
Pandas 使用 (2)
xml
用 tornado 做網(wǎng)站 (5)
文件(1)
練習(xí)
列表(3)
從小工到專家
除法
錯誤和異常 (2)
函數(shù)(1)
用 tornado 做網(wǎng)站 (7)
為做網(wǎng)站而準(zhǔn)備
函數(shù)練習(xí)
標(biāo)準(zhǔn)庫 (8)
Pandas 使用 (1)
回顧 list 和 str
字典(1)
用 tornado 做網(wǎng)站 (3)
字符串(1)
函數(shù)(2)
寫一個簡單的程序
將數(shù)據(jù)存入文件
語句(5)
SQLite 數(shù)據(jù)庫
集成開發(fā)環(huán)境(IDE)
集合(1)
類(1)
用 tornado 做網(wǎng)站 (6)
用 tornado 做網(wǎng)站 (2)
自省
語句(4)
錯誤和異常 (1)
用 tornado 做網(wǎng)站 (4)
集合(2)
列表(1)
標(biāo)準(zhǔn)庫 (1)
生成器
mysql 數(shù)據(jù)庫 (1)
第三方庫
實(shí)戰(zhàn)
運(yùn)算符
類(3)
字典(2)
語句(1)
數(shù)和四則運(yùn)算
語句(2)
文件(2)
MySQL 數(shù)據(jù)庫 (2)
電子表格
迭代器
mongodb 數(shù)據(jù)庫 (1)
特殊方法 (2)
特殊方法 (1)
字符編碼
編寫模塊
用 tornado 做網(wǎng)站 (1)
標(biāo)準(zhǔn)庫 (5)
函數(shù)(4)
類(5)
字符串(2)
關(guān)于 Python 的故事
函數(shù)(3)
字符串(4)
處理股票數(shù)據(jù)
常用數(shù)學(xué)函數(shù)和運(yùn)算優(yōu)先級
字符串(3)
為計算做準(zhǔn)備
多態(tài)和封裝
類(4)
迭代
語句(3)
錯誤和異常 (3)
分析 Hello
Python 安裝
標(biāo)準(zhǔn)庫 (2)
列表(2)
元組

集合(1)

回顧一下已經(jīng)學(xué)過的數(shù)據(jù)類型:int/str/bool/list/dict/tuple

還真的不少了.

不過,Python 是一個發(fā)展的語言,沒準(zhǔn)以后還出別的呢.看官可能有疑問了,出了這么多的數(shù)據(jù)類型,我也記不住呀,特別是里面還有不少方法.

不要擔(dān)心記不住,你只要記住愛因斯坦說的就好了.

愛因斯坦在美國演講,有人問:“你可記得聲音的速度是多少?你如何記下許多東西?”

愛因斯坦輕松答道:“聲音的速度是多少,我必須查辭典才能回答。因為我從來不記在辭典上已經(jīng)印著的東西,我的記憶力是用來記憶書本上沒有的東西?!?/p>

多么霸氣的回答,這回答不僅僅霸氣,更告訴我們一種方法:只要能夠通過某種方法查找到的,就不需要記憶.

那么,上面那么多數(shù)據(jù)類型及其各種方法,都不需要記憶了,因為它們都可以通過下述方法但不限于這些方法查到(這句話的邏輯還是比較嚴(yán)密的,包括但不限于...)

  • 交互模式下用 dir()或者 help()
  • google(不推薦 Xdu,原因自己體會啦)

在已經(jīng)學(xué)過的數(shù)據(jù)類型中:

  • 能夠索引的,如 list/str,其中的元素可以重復(fù)
  • 可變的,如 list/dict,即其中的元素/鍵值對可以原地修改
  • 不可變的,如 str/int,即不能進(jìn)行原地修改
  • 無索引序列的,如 dict,即其中的元素(鍵值對)沒有排列順序

現(xiàn)在要介紹另外一種類型的數(shù)據(jù),英文是 set,翻譯過來叫做“集合”。它的特點(diǎn)是:有的可變,有的不可變;元素?zé)o次序,不可重復(fù)。

創(chuàng)建 set

tuple 算是 list 和 str 的雜合(雜交的都有自己的優(yōu)勢,上一節(jié)的末后已經(jīng)顯示了),那么 set 則可以堪稱是 list 和 dict 的雜合.

set 擁有類似 dict 的特點(diǎn):可以用{}花括號來定義;其中的元素沒有序列,也就是是非序列類型的數(shù)據(jù);而且,set 中的元素不可重復(fù),這就類似 dict 的鍵.

set 也有一點(diǎn) list 的特點(diǎn):有一種集合可以原處修改.

下面通過實(shí)驗,進(jìn)一步理解創(chuàng)建 set 的方法:

>>> s1 = set("qiwsir")  
>>> s1                  
set(['q', 'i', 's', 'r', 'w'])

把 str 中的字符拆解開,形成 set.特別注意觀察:qiwsir 中有兩個 i,但是在 s1 中,只有一個 i,也就是集合中元素不能重復(fù)。

>>> s2 = set([123,"google","face","book","facebook","book"])
>>> s2
set(['facebook', 123, 'google', 'book', 'face'])                

在創(chuàng)建集合的時候,如果發(fā)現(xiàn)了重復(fù)的元素,就會過濾一下,剩下不重復(fù)的。而且,從 s2 的創(chuàng)建可以看出,查看結(jié)果是顯示的元素順序排列與開始建立是不同,完全是隨意顯示的,這說明集合中的元素沒有序列。

>>> s3 = {"facebook",123}       #通過{}直接創(chuàng)建
>>> s3
set([123, 'facebook'])

除了用 set()來創(chuàng)建集合。還可以使用{}的方式,但是這種方式不提倡使用,因為在某些情況下,Python 搞不清楚是字典還是集合。看看下面的探討就發(fā)現(xiàn)問題了。

>>> 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'

從上述實(shí)驗中,可以看出,通過{}無法創(chuàng)建含有 list/dict 元素的 set.

認(rèn)真閱讀報錯信息,有這樣的詞匯:“unhashable”,在理解這個詞之前,先看它的反義詞“hashable”,很多時候翻譯為“可哈?!保鋵?shí)它有一個不是音譯的名詞“散列”,這個在《字典(1)》中有說明。網(wǎng)上搜一下,有不少文章對這個進(jìn)行詮釋。如果我們簡單點(diǎn)理解,某數(shù)據(jù)“不可哈?!?unhashable)就是其可變,如 list/dict,都能原地修改,就是 unhashable。否則,不可變的,類似 str 那樣不能原地修改,就是 hashable(可哈希)的。

對于前面已經(jīng)提到的字典,其鍵必須是 hashable 數(shù)據(jù),即不可變的。

現(xiàn)在遇到的集合,其元素也要是“可哈?!钡?。上面例子中,試圖將字典、列表作為元素的元素,就報錯了。而且報錯信息中明確告知 list/dict 是不可哈希類型,言外之意,里面的元素都應(yīng)該是可哈希類型。

繼續(xù)探索一個情況:

>>> 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

這里報錯,進(jìn)一步說明集合沒有序列,不能用索引方式對其進(jìn)行修改。

>>> 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()能夠?qū)崿F(xiàn)兩種數(shù)據(jù)類型之間的轉(zhuǎn)化。

特別說明,利用 set()建立起來的集合是可變集合,可變集合都是 unhashable 類型的。

set 的方法

還是用前面已經(jīng)介紹過多次的自學(xué)方法,把 set 的有關(guān)內(nèi)置函數(shù)找出來,看看都可以對 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()可以找到每個函數(shù)的具體使用方法,下面列幾個例子:

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.

下面在交互模式這個最好的實(shí)驗室里面做實(shí)驗:

>>> a_set = {}              #我想當(dāng)然地認(rèn)為這樣也可以建立一個 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 之后發(fā)現(xiàn),計算機(jī)認(rèn)為我建立的是一個 dict     
<type 'dict'>

特別說明一下,{}這個東西,在 dict 和 set 中都用.但是,如上面的方法建立的是 dict,不是 set.這是 Python 規(guī)定的.要建立 set,只能用前面介紹的方法了.

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

>>> a_set.add("qiwsir")     #增加一個元素
>>> a_set                   #原處修改,即原來的 a_set 引用對象已經(jīng)改變
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 是不可哈希的,集合中的元素應(yīng)該是 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'])

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()不能有參數(shù).此外,如果 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

知識

集合,也是一個數(shù)學(xué)概念(以下定義來自維基百科)

集合(或簡稱集)是基本的數(shù)學(xué)概念,它是集合論的研究對象。最簡單的說法,即是在最原始的集合論─樸素集合論─中的定義,集合就是“一堆東西”。集合里的“東西”,叫作元素。若然 x 是集合 A 的元素,記作 x ∈ A。

集合是現(xiàn)代數(shù)學(xué)中一個重要的基本概念。集合論的基本理論直到十九世紀(jì)末才被創(chuàng)立,現(xiàn)在已經(jīng)是數(shù)學(xué)教育中一個普遍存在的部分,在小學(xué)時就開始學(xué)習(xí)了。這里對被數(shù)學(xué)家們稱為“直觀的”或“樸素的”集合論進(jìn)行一個簡短而基本的介紹;更詳細(xì)的分析可見樸素集合論。對集合進(jìn)行嚴(yán)格的公理推導(dǎo)可見公理化集合論。

在計算機(jī)中,集合是什么呢?同樣來自維基百科,這么說的:

在計算機(jī)科學(xué)中,集合是一組可變數(shù)量的數(shù)據(jù)項(也可能是 0 個)的組合,這些數(shù)據(jù)項可能共享某些特征,需要以某種操作方式一起進(jìn)行操作。一般來講,這些數(shù)據(jù)項的類型是相同的,或基類相同(若使用的語言支持繼承)。列表(或數(shù)組)通常不被認(rèn)為是集合,因為其大小固定,但事實(shí)上它常常在實(shí)現(xiàn)中作為某些形式的集合使用。

集合的種類包括列表,集,多重集,樹和圖。枚舉類型可以是列表或集。

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

是的,所以本講僅僅是對集合有一個入門.關(guān)于集合的更多操作如運(yùn)算/比較等,還沒有涉及呢.


總目錄   |   上節(jié):字典(2)   |   下節(jié):集合(2)

如果你認(rèn)為有必要打賞我,請通過支付寶:qiwsir@126.com,不勝感激。

上一篇:寫一個簡單的程序下一篇:列表(2)