第三章(提煉)字典和集合(三)

一. 集合論

集合的本質是許多唯一對象的聚集,因此,集合可以用於去重:

集合中的元素必須是可散列的,set 類型本身是不可散列的,但是 frozenset 可以。除了保證唯一性,集合還實現了很多基礎的中綴運算符。給定兩個集合 a 和 ba | b 返回的是它們的合集,a & b 得到的是交集,而 a - b 得到的是差集。

演示1  needles 的元素在 haystack 裏出現的次數,兩個變量都是 set 類型

演示2  needles 的元素在 haystack 裏出現的次數,這次的代碼可以用在任何可迭代對象上

以上的所有例子的運行時間都能在 3 毫秒左右,在含有 10 000 000 個元素的 haystack 裏搜索 1000 個值,算下來大概是每個元素 3 微秒。除了速度極快的查找功能(這也得歸功於它背後的散列表),內置的 set 和 frozenset 提供了豐富的功能和操作,不但讓創建集合的方式豐富多彩,而且對於 set 來講,我們還可以對集合裏已有的元素進行修改。

1.1 集合字面量

除空集之外,集合的字面量——{1}{1, 2},等等——看起來跟它的數學形式一模一樣。如果是空集,那麼必須寫成 set() 的形式,如果只是寫成 {} 的形式,跟以前一樣,你創建的其實是個空字典。

像 {1, 2, 3} 這種字面量句法相比於構造方法(set([1, 2, 3]))要更快且更易讀。用 dis.dis(反彙編函數)來看看兩個方法的字節碼的不同:

特殊的字節碼 BUILD_SET 幾乎完成了所有的工作。而使用set()創建時,3 種不同的操作代替了上面的 BUILD_SET:LOAD_NAMEBUILD_LIST CALL_FUNCTION。 

由於 Python 裏沒有針對 frozenset 的特殊字面量句法,我們只能採用構造方法:

1.2 集合推導

演示2  新建一個 Latin-1 字符集合,該集合裏的每個字符的 Unicode 名字裏都有“SIGN”這個單詞

unicodedata 模塊裏導入 name 函數,用以獲取字符的名字。把編碼在 32~255 之間的字符的名字裏有“SIGN”單詞的挑出來,放到一個集合裏。

1.3 集合的操作

列出了可變和不可變集合所擁有的方法的概況,其中不少是運算符重載的特殊方法。

中綴運算符需要兩側的被操作對象都是集合類型,但是其他的所有方法則只要求所傳入的參數是可迭代對象。例如,想求 4 個聚合類型 abc d 的合集,可以用 a.union(b, c, d),這裏 a 必須是個 set,但是 bc d 則可以是任何類型的可迭代對象。

表 1-1:集合的數學運算:這些方法或者會生成新集合,或者會在條件允許的情況下就地修改集合

數學符號 Python運算符 方法 描述
S ∩ Z s & z s.__add__(z)
s z 的交集
z & s s.__radd__(z)
反向 & 操作
s.intersection(it, ...)
把可迭代的 it 和其他所有參數轉化爲集合,然後求它們與 s 的交集
s &= z
s.__iand__(z)
s 更新爲 s z 的交集
s.intersection_update(it, ...)
把可迭代的 it 和其他所有參數轉化爲集合,然後求得它們與 s 的交集,然後把 s 更新成這個交集
S ∪ Z
s | z
s.__or__(z)
s z 的並集
z | s
s.__ror__(z)
| 的反向操作
s.union(it, ...)
把可迭代的 it 和其他所有參數轉化爲集合,然後求它們和 s 的並集
s |= z
s.__ior__(z)
s 更新爲 s z 的並集
s.update(it, ...)
把可迭代的 it 和其他所有參數轉化爲集合,然後求它們和 s 的並集,並把 s 更新成這個並集
S \ Z
s - z s.__sub__(z)
s z 的差集,或者叫作相對補集
z - s s.__rsub__(z)
- 的反向操作
s.difference(it, ...)
把可迭代的 it 和其他所有參數轉化爲集合,然後求它們和 s 的差集
s -= z s.__isub__(z)
s 更新爲它與 z 的差集
s.difference_update(it, ...)
把可迭代的 it 和其他所有參數轉化爲集合,求它們和 s 的差集,然後把 s 更新成這個差集
s.symmetric_difference(it)
s set(it) 的對稱差集
S △ Z
s ^ z
s.__xor__(z)
s z 的對稱差集
z ^ s
s.__rxor__(z)
^ 的反向操作
s.symmetric_difference_update(it, ...)
把可迭代的 it 和其他所有參數轉化爲集合,然後求它們和 s 的對稱差集,最後把 s 更新成該結果
s ^= z
s.__ixor__(z)
s 更新成它與 z 的對稱差集

表 1-2:集合的比較運算符,返回值是布爾類型

數學符號 Python運算符 方法 描述
—— —— s.isdisjoint(z)
查看 s z 是否不相交(沒有共同元素)
e S
e in s s.__contains__(e)
元素 e 是否屬於 s
S Z
s <= z s.__le__(z)
s 是否爲 z 的子集
s.issubset(it)
把可迭代的 it 轉化爲集合,然後查看 s 是否爲它的子集
S Z
s < z s.__lt__(z)
s 是否爲 z 的真子集
S Z
s >= z s.__ge__(z)
s 是否爲 z 的父集
s.issuperset(it)
把可迭代的 it 轉化爲集合,然後查看 s 是否爲它的父集
S Z
s > z s.__gt__(z)
s 是否爲 z 的真父集

 表 1-3:集合類型的其他方法

方法 set frozenset 描述
s.add(e) ×
把元素 e 添加到 s
s.clear()
×
移除掉 s 中的所有元素
s.copy()
s 淺複製
s.discard(e)
×
如果 s 裏有 e 這個元素的話,把它移除
s.__iter__()
返回 s 的迭代器
s.__len__()
len(s)
s.pop()
×
s 中移除一個元素並返回它的值,若 s 爲空,則拋出 KeyError 異常
s.remove(e)
×
s 中移除 e 元素,若 e 元素不存在,則拋出 KeyError 異常

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章