python中集合和字典的使用

集合
集合set是裝有獨特值的無序“袋子”。一個簡單的集合可以包含任何數據類型的值。如果有兩個集合,則可以執行像聯合、交集以及集合求差等標準集合運算。
創建集合
重中之重。創建集合非常簡單。

>>> a_set = {1}①
>>> a_set

{1}

>>> type(a_set)

class “set”

>>> a_set = {1, 2}③
>>> a_set

{1, 2}
要創建只包含一個值的集合,僅需將該值放置於花括號之間。({})。
實際上,集合以 類 的形式實現,但目前還無須考慮這一點。
要創建多值集合,請將值用逗號分開,並用花括號將所有值包裹起來。

還可以 列表 爲基礎創建集合。

>>> a_list = ["a", "b", "mpilgrim", True, False, 42]
>>> a_set = set(a_list)①
>>> a_set

{“a”, False, “b”, True, “mpilgrim”, 42}

>>> a_list③

[“a”, “b”, “mpilgrim”, True, False, 42]
要從列表創建集合,可使用 set() 函數。(懂得如何實現集合的學究可能指出這實際上並不是調用某個函數,而是對某個類進行實例化。我保證在本書稍後的地方將會學到其中的區別。目前而言,僅需知道 set() 行爲與函數類似,以及它返回一個集合。)
正如我之前提到的,簡單的集合可以包括任何數據類型的值。而且,如我之前所提到的,集合是 無序的。該集合並不記得用於創建它的列表中元素的最初順序。如果向集合中添加元素,它也不會記得添加的順序。
初始的列表並不會發生變化。

還沒有任何值?沒有問題。可以創建一個空的集合。

>>> a_set = set()①
>>> a_set

set()

>>> type(a_set)

class “set”

>>> len(a_set)④

0

>>> not_sure = {}⑤
>>> type(not_sure)

class “dict”
要創建空集合,可不帶參數調用 set() 。
打印出來的空集合表現形式看起來有點兒怪。也許,您期望看到一個 {} 吧 ?該符號表示一個空的字典,而不是一個空的集合。本章稍後您將學到關於字典的內容。
儘管打印出的形式奇怪,這 確實是 一個集合……
…… 同時該集合沒有任何成員。
由於從 Python 2 沿襲而來歷史的古怪規定,不能使用兩個花括號來創建空集合。該操作實際創建一個空字典,而不是一個空集合。
修改集合
有兩種方法可向現有集合中添加值: add() 方法和 update() 方法。

>>> a_set = {1, 2}
>>> a_set.add(4)①
>>> a_set

{1, 2, 4}

>>> len(a_set)②

3

>>> a_set.add(1)③
>>> a_set

{1, 2, 4}

>>> len(a_set)④

3
add() 方法接受單個可以是任何數據類型的參數,並將該值添加到集合之中。
該集合現在有三個成員了。
集合是裝 唯一值 的袋子。如果試圖添加一個集合中已有的值,將不會發生任何事情。將不會引發一個錯誤;只是一條空操作。
該集合 仍然 只有三個成員。

>>> a_set = {1, 2, 3}
>>> a_set

{1, 2, 3}

>>> a_set.update({2, 4, 6})①
>>> a_set②

{1, 2, 3, 4, 6}

>>> a_set.update({3, 6, 9}, {1, 2, 3, 5, 8, 13})③
>>> a_set

{1, 2, 3, 4, 5, 6, 8, 9, 13}

>>> a_set.update([10, 20, 30])④
>>> a_set

{1, 2, 3, 4, 5, 6, 8, 9, 10, 13, 20, 30}
update() 方法僅接受一個集合作爲參數,並將其所有成員添加到初始列表中。其行爲方式就像是對參數集合中的每個成員調用 add() 方法。
由於集合不能包含重複的值,因此重複的值將會被忽略。
實際上,可以帶任何數量的參數調用 update() 方法。如果調用時傳遞了兩個集合, update() 將會被每個集合中的每個成員添加到初始的集合當中(丟棄重複值)。
update() 方法還可接受一些其它數據類型的對象作爲參數,包括列表。如果調用時傳入列表,update() 將會把列表中所有的元素添加到初始集合中。
從集合中刪除元素
有三種方法可以用來從集合中刪除某個值。前兩種,discard() 和 remove() 有細微的差異。

>>> a_set = {1, 3, 6, 10, 15, 21, 28, 36, 45}
>>> a_set

{1, 3, 36, 6, 10, 45, 15, 21, 28}

>>> a_set.discard(10)①
>>> a_set

{1, 3, 36, 6, 45, 15, 21, 28}

>>> a_set.discard(10)②
>>> a_set

{1, 3, 36, 6, 45, 15, 21, 28}

>>> a_set.remove(21)③
>>> a_set

{1, 3, 36, 6, 45, 15, 28}

>>> a_set.remove(21)④

Traceback (most recent call last): File “”, line 1, in KeyError: 21
discard() 接受一個單值作爲參數,並從集合中刪除該值。
如果針對一個集合中不存在的值調用 discard() 方法,它不進行任何操作。不產生錯誤;只是一條空指令。
remove() 方法也接受一個單值作爲參數,也從集合中將其刪除。
區別在這裏:如果該值不在集合中,remove() 方法引發一個 KeyError 例外。

就像列表,集合也有個 pop() 方法。

>>> a_set = {1, 3, 6, 10, 15, 21, 28, 36, 45}
>>> a_set.pop()①

1

>>> a_set.pop()

3

>>> a_set.pop()

36

>>> a_set

{6, 10, 45, 15, 21, 28}

>>> a_set.clear()②
>>> a_set

set()

>>> a_set.pop()③

Traceback (most recent call last): File “”, line 1, in KeyError: “pop from an empty set”
pop() 方法從集合中刪除某個值,並返回該值。然而,由於集合是無序的,並沒有“最後一個”值的概念,因此無法控制刪除的是哪一個值。它基本上是隨機的。
clear() 方法刪除集合中 所有 的值,留下一個空集合。它等價於 a_set = set(),該語句創建一個新的空集合,並用之覆蓋a_set變量的之前的值。
試圖從空集合中彈出某值將會引發 KeyError 例外。
常見集合操作
Python 的 集合 類型支持幾種常見的運算。

>>> a_set = {2, 4, 5, 9, 12, 21, 30, 51, 76, 127, 195}
>>> 30 in a_set

True

>>> 31 in a_set

False

>>> b_set = {1, 2, 3, 5, 6, 8, 9, 12, 15, 17, 18, 21}
>>> a_set.union(b_set)②

{1, 2, 195, 4, 5, 6, 8, 12, 76, 15, 17, 18, 3, 21, 30, 51, 9, 127}

>>> a_set.intersection(b_set)③

{9, 2, 12, 5, 21}

>>> a_set.difference(b_set)④

{195, 4, 76, 51, 30, 127}

>>> a_set.symmetric_difference(b_set)⑤

{1, 3, 4, 6, 8, 76, 15, 17, 18, 195, 127, 30, 51}
要檢測某值是否是集合的成員,可使用 in 運算符。其工作原理和列表的一樣。
union() 方法返回一個新集合,其中裝着 在兩個 集合中出現的元素。
intersection() 方法返回一個新集合,其中裝着 同時 在兩個集合中出現的所有元素。
difference() 方法返回的新集合中,裝着所有在a_set出現但未在b_set中的元素。
symmetric_difference() 方法返回一個新集合,其中裝着所有 只在其中一個 集合中出現的元素。

這三種方法是對稱的。

continued from the previous example

>>> b_set.symmetric_difference(a_set)①

{3, 1, 195, 4, 6, 8, 76, 15, 17, 18, 51, 30, 127}

>>> b_set.symmetric_difference(a_set) == a_set.symmetric_difference(b_set)②

True

>>> b_set.union(a_set) == a_set.union(b_set)③

True

>>> b_set.intersection(a_set) == a_set.intersection(b_set)④

True

>>> b_set.difference(a_set) == a_set.difference(b_set)⑤

False
a_set與b_set的對稱差分 看起來 和b_set與a_set的對稱差分不同,但請記住:集合是無序的。任何兩個包含所有同樣值(無一遺漏)的集合可認爲是相等的。
而這正是這裏發生的事情。不要被 Python Shell 對這些集合的輸出形式所愚弄了。它們包含相同的值,因此是相等的。
對兩個集合的 Union[並集]操作也是對稱的。
對兩個集合的 Intersection[交集]操作也是對稱的。
對兩個集合的 Difference[求差]操作不是對稱的。這是有意義的;它類似於從一個數中減去另一個數。操作數的順序會導致結果不同。

最後,有幾個您可能會問到的問題。

>>> a_set = {1, 2, 3}
>>> b_set = {1, 2, 3, 4}
>>> a_set.issubset(b_set)①

True

>>> b_set.issuperset(a_set)②

True

>>> a_set.add(5)③
>>> a_set.issubset(b_set)

False

>>> b_set.issuperset(a_set)

False
a_set是b_set的子集— 所有a_set的成員均爲b_set的成員。
同樣的問題反過來說,b_set是a_set的超集,因爲a_set的所有成員均爲b_set的成員。
一旦向a_set添加一個未在b_set中出現的值,兩項測試均返回 False 。
布爾上下文環境中的集合
可在 if 這樣的 布爾類型上下文環境中 使用集合。

>>> def is_it_true(anything):

… if anything:
… print(“yes, it”s true”)
… else:
… print(“no, it”s false”)

>>> is_it_true(set())①

no, it”s false

>>> is_it_true({"a"})②

yes, it”s true

>>> is_it_true({False})③

yes, it”s true
在布爾類型上下文環境中,空集合爲假值。
任何至少包含一個上元素的集合爲真值。
任何至少包含一個上元素的集合爲真值。元素的值無關緊要。

字典
字典是鍵值對的無序集合。向字典添加一個鍵的同時,必須爲該鍵增添一個值。(之後可隨時修改該值。) Python 的字典爲通過鍵獲取值進行了優化,而不是反過來。
☞Python 中的字典與 Perl 5 中的 hash [散列]類似。在 Perl 5 中,散列存儲的變量總是以一個 % 符開頭。在 Python 中,變量可以隨意命名,而 Python 內部跟蹤其數據類型。
創建字典
創建字典非常簡單。其語法與 集合 的類似,但應當指定鍵值對而不是值。有了字典後,可以通過鍵來查找值。

>>> a_dict = {"server": "db.diveintopython3.org", "database": "mysql"}①
>>> a_dict

{“server”: “db.diveintopython3.org”, “database”: “mysql”}

>>> a_dict["server"]②

“db.diveintopython3.org”

>>> a_dict["database"]③

“mysql”

>>> a_dict["db.diveintopython3.org"]④

Traceback (most recent call last): File “”, line 1, in KeyError: “db.diveintopython3.org”
首先,通過將兩個字典項指定給a_dict變量創建了一個新字典。每個字典項都是一組鍵值對,整個字典項集合都被大括號包裹在內。
“server” 爲鍵,通過 a_dict[“server”] 引用的關聯值爲 “db.diveintopython3.org” 。
“database” 爲鍵,通過 a_dict[“database”] 引用的關聯值爲 “mysql” 。
可以通過鍵獲取值,但不能通過值獲取鍵。因此 a_dict[“server”] 爲 “db.diveintopython3.org”,而 a_dict[“db.diveintopython3.org”] 會引發例外,因爲 “db.diveintopython3.org” 並不是鍵。
修改字典
字典沒有預定義的大小限制。可以隨時向字典中添加新的鍵值對,或者修改現有鍵所關聯的值。繼續前面的例子:

>>> a_dict

{“server”: “db.diveintopython3.org”, “database”: “mysql”}

>>> a_dict["database"] = "blog">>> a_dict

{“server”: “db.diveintopython3.org”, “database”: “blog”}

>>> a_dict["user"] = "mark">>> a_dict③

{“server”: “db.diveintopython3.org”, “user”: “mark”, “database”: “blog”}

>>> a_dict["user"] = "dora">>> a_dict

{“server”: “db.diveintopython3.org”, “user”: “dora”, “database”: “blog”}

>>> a_dict["User"] = "mark">>> a_dict

{“User”: “mark”, “server”: “db.diveintopython3.org”, “user”: “dora”, “database”: “blog”}
在字典中不允許有重複的鍵。對現有的鍵賦值將會覆蓋舊值。
可隨時添加新的鍵值對。該語法與修改現有值相同。
新字典項(鍵爲 “user”,值爲 “mark”)出現在中間。事實上,在第一個例子中字典項按順序出現是個巧合;現在它們不按順序出現同樣也是個巧合。
對既有字典鍵進行賦值只會用新值替代舊值。
該操作會將 user 鍵的值改回 “mark” 嗎?不會!仔細看看該鍵——有個大寫的U出現在”User”中。字典鍵是區分大小寫的,因此該語句創建了一組新的鍵值對,而不是覆蓋既有的字典項。對你來說它們可能是一樣的,但對於 Python 而言它們是完全不同的。
混合值字典

典並非只能用於字符串。字典的值可以是任何數據類型,包括整數、布爾值、任何對象,甚至是其它的字典。而且就算在同一字典中,所有的值也無須是同一類型,
您可根據需要混合匹配。字典的鍵要嚴格得多,可以是字符串、整數和其它一些類型。在同一字典中也可混合、匹配使用不同數據類型的鍵。
實際上,您已經在 your first Python program 見過一個將非字符串用作鍵的字典了。
SUFFIXES = {1000: [“KB”, “MB”, “GB”, “TB”, “PB”, “EB”, “ZB”, “YB”],
1024: [“KiB”, “MiB”, “GiB”, “TiB”, “PiB”, “EiB”, “ZiB”, “YiB”]}

讓我們在交互式 shell 中剖析一下:

>>> SUFFIXES = {1000: ["KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"],

… 1024: [“KiB”, “MiB”, “GiB”, “TiB”, “PiB”, “EiB”, “ZiB”, “YiB”]}

>>> len(SUFFIXES)①

2

>>> 1000 in SUFFIXES②

True

>>> SUFFIXES[1000]

[“KB”, “MB”, “GB”, “TB”, “PB”, “EB”, “ZB”, “YB”]

>>> SUFFIXES[1024]

[“KiB”, “MiB”, “GiB”, “TiB”, “PiB”, “EiB”, “ZiB”, “YiB”]

>>> SUFFIXES[1000][3]⑤

“TB”
類似 列表 和 集合 ,len() 函數將返回字典中鍵的數量。
而且像列表和集合一樣,可使用 in 運算符以測試某個特定的鍵是否在字典中。
1000 是 字典 SUFFIXES 的一個鍵;其值爲一個 8 元素列表(確切地說,是 8 個字符串)。
同樣, 1024 是字典 SUFFIXES 的鍵;其值也是一個 8 元素列表。
由於 SUFFIXES[1000] 是列表,可以通過它們的 0 基點索引來獲取列表中的單個元素。
布爾上下文環境中的字典
空字典爲假值;所有其它字典爲真值。

可以在 if 這樣的 布爾類型上下文環境中 使用字典。

>>> def is_it_true(anything):

… if anything:
… print(“yes, it”s true”)
… else:
… print(“no, it”s false”)

>>> is_it_true({})①

no, it”s false

>>> is_it_true({"a": 1})②

yes, it”s true
在布爾類型上下文環境中,空字典爲假值。
至少包含一個鍵值對的字典爲真值。

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