O slideshow foi denunciado.
Seu SlideShare está sendo baixado. ×

9. 資料結構

Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Próximos SlideShares
13.並行、平行與非同步
13.並行、平行與非同步
Carregando em…3
×

Confira estes a seguir

1 de 73 Anúncio

Mais Conteúdo rRelacionado

Diapositivos para si (20)

Anúncio

Mais de Justin Lin (20)

Mais recentes (20)

Anúncio

9. 資料結構

  1. 1. 9. 資料結構 • 學習目標 – 認識 hashable、iterable、 orderable – 對物件進行排序 – 認識群集架構 – 運用 collections 模組 – 運用 collections.abc 模組 2
  2. 2. hashable 協定 • 試圖在 set 中置放這些型態的實例,就會 引發 TypeError: 3
  3. 3. • 一個物件能被稱為 hashable,它必須有個 hash 值 • 這個值在整個執行時期都不會變化, 而且 必須可以進行相等比較 • 具體來說, 一個物件能被稱為 hashable, 必須實作 __hash__() 與 __eq__() 方法 4
  4. 4. • set 會對加入之物件,呼叫其 __hash__() 方法取得 hash 值 • 看它是否與目前 set 中既有物件的 hash 值都不相同 – 如果相同就會直接排除而不加入 – 若都不相同,則進一步使用 __eq__() 比較 相等性,以確定是否要加入 set 之中 5
  5. 5. • 對於 Python 內建型態來說,只要是建立後 – 狀態就無法變動(Immutable)的型態,它的 實例都是 hashable – 可變動(Muttable)的型態之實例,都是 unhashable 6
  6. 6. • 一個自定義的類別建立的實例,預設也是 hashable 的 – 其 __hash__() 實作,基本上是根據 id() 計 算而來 – 而 __eq__() 實作,預設是使用 is 來比較 – 因此,兩個分別建立的實例,hash 值必然不相 同,而且相等性比較一定不成立 7
  7. 7. • 什麼樣的狀態會被認定為重複,還是要自 行定義 __hash__() 與 __eq__(): 8
  8. 8. 9
  9. 9. • hashable 物件,建議狀態是不可變動 • 兩個物件若是相等性比較成立,那麼也必 須有相同的 hash 值 • 然而 hash 值相同,兩個物件的相等性比較 不一定是成立的 10
  10. 10. 使用dataclass • Point類別單純地用來封裝一些簡單的欄 位, 這樣的類別稱為資料類別(Data class) • 3.7新增dataclasses.dataclass 11
  11. 11. 12
  12. 12. • 在使用@dataclass標註時,指定 frozen=True 13
  13. 13. • 也可以設定init、repr、eq、order等 參數,表明要不要產生對應的協定方法 • unsafe_hash預設是False,若被設為 True,就一定會加入__hash__() • 被標註的類別也可以指定欄位預設值 14
  14. 14. • 預設值不能是可變動的實例,例如list, 這會引發錯誤: 15
  15. 15. • 可以使用field指定default_factory • 想臨時建立Point這樣的類別,也可以使 用dataclasses的make_dataclass() 16
  16. 16. • 如果要標註型態、預設值或不可變動的話 • asdict()用來將@dataclass標註的類別 之實例,轉換為dict 17
  17. 17. iterable 協定 • 具有 __iter__() 方法的物件,就是一個 iterable 物件 • 傳回的迭代器具有 __next__() 方法,可 以逐一迭代出物件中,的資訊,若無法進 一步迭代,會引發 StopIteration • 迭代器也會具有 __iter__() 方法,傳回 迭代器自身,因此,每個迭代器本身也是 個 iterable 物件 18
  18. 18. 19
  19. 19. • 對於狀態比較複雜的物件來說,有時產生 器不見得適合時,就會親自實作 __iter__()等方法來建立迭代器 20
  20. 20. 21
  21. 21. • 同樣的需求,也可以使用產生器來實作 22
  22. 22. • 標準程式庫有許多情況下,都接受iterable 物件,在內部自動呼叫 __iter__() • 若 lt 是[1, 2, 3, 4, 5]: –set(lt) 會建立 {1, 2, 3} –tuple(lt) 會建立 (1, 2, 3, 4, 5) 23
  23. 23. • 標準程式庫中提供了 itertools 模組,當 中許多函式,可協助建立迭代器或產生器 24
  24. 24. • accumulate() 可在迭代的過程中進行累 加或指定的運算: • chain() 或 chain.from_iterable() 可將指定的序列攤平逐一迭代: 25
  25. 25. • dropwhile()、takewhile()、 filterfalse() 26
  26. 26. • 有時候會需要依某個鍵來進行分類 27
  27. 27. • 使用 itertools 的 groupby() 函式可以 省事許多: 28
  28. 28. orderable 協定 • 如果打算對一個 list 進行排序,可以直接 呼叫它的 sort() 方法,這會在既有的 list 上進行排序: 29
  29. 29. • 也可以使用 key 參數,指定要使用哪個值 進行排序: 30
  30. 30. • list 才有 sort() 方法 • 對於其他 iterable 物件,若想進行排序的 話,可以使用 sorted() 函式,可指定的 參數同樣也有 reverse 與 key 參數 • 此函式不會變動原有的函式,排序的結果 會以新的 list 傳回 31
  31. 31. • 如果是自訂的類別實例,它們怎麼會知道 該怎麼排序呢? 32
  32. 32. • 如果希望自訂型態在 sorted() 或者是使 用 list 的 sort() 時,可以有預設的排 序定義,必須實作 __lt__() 方法: 33
  33. 33. 34
  34. 34. • 可以指定 operator 模組的 itemgetter,、 attrgetter,前者可以針對具有索引的 結構,後者可以針對物件的屬性: 35
  35. 35. 36
  36. 36. 認識群集架構 • 群集分為三種類型: – 循序類型(Sequences type) – 集合類型(Set type) – 映射類型(Mapping type) 37
  37. 37. • 循序類型都是有序、具備索引的資料結構, 循序類型都是 iterable 物件 38
  38. 38. • tuple、str 與 bytes 是不可變動的循序 類型,具有預設的 hash()實作 • 可變動循序結構,還會有以下的操作行為: 39
  39. 39. • 集合類型是無序,而且元素必須都是 hashable 物件而且不會重複,它們是 iterable 物件 • 可以使用 x in set、x not in set、 len(set),以及交集、聯集、差集與對稱 差集等操作 • set 本身是可變動的,如果想要不可變動 的集合類型,可以使用 frozenset() 來 建立 40
  40. 40. • 映射類型可以將 hashable 物件映射至一個 任意值 • Python 中的內建型態就是 dict 41
  41. 41. • 如果想實作先進後出的堆疊結構,可以使 用 list,運用 append() 與 pop() 方法 42
  42. 42. • 對於佇列或雙向佇列來說,使用 list 的效 率並不好 • 建議使用 collections 模組中提供的 deque 類別 43
  43. 43. • 有個 rotate()方法,可實作出環狀佇列 44
  44. 44. • 有個簡單類別,以便建立的實例能擁有欄 位名稱,可以使用 collections 模組的 namedtuple() 函式 45
  45. 45. 46
  46. 46. • namedtuple()傳回的類別,建構出的實 例不可變動 • 本質上還是tuple,只是被額外賦予名稱 • 不要濫用namedtuple() 47
  47. 47. • 如果來源是個 iterable 物件, 除了 Point(*iterable) 的方式之外,還可 以使用 Point._make(iterable) 建立 Point 實例 48
  48. 48. 49
  49. 49. • 要指定欄位型態,typing.NamedTuple 提供了這個功能 • 另一方式是透過繼承NamedTuple來定義 50
  50. 50. • 若想以一定的順序來走訪 dict 中鍵值 51
  51. 51. • 如果想要在建立 dict 時保有最初鍵值加入 的順序,可以使用 collections 模組的 OrderedDict 52
  52. 52. • 依鍵排序或依值排序的常見需求: 53
  53. 53. 54
  54. 54. • 用 collections 的 defaultdict 類別 • defaultdict 接受一個函式,它建立的實 例在當指定的鍵不存在時,就會使用指定 的函式來產生,並直接設定為鍵的對應值 55
  55. 55. • 使用 defaultdict 來設計一個計數器 56
  56. 56. • collections 模組中就個 Counter 類別 57
  57. 57. • 可以指定一個 dict 給 Counter,它會依 dict 中值的指定,建立對應數量的鍵 58
  58. 58. • 有多個 dict 物件,想要將它們合併在一起 59
  59. 59. • 可以使用 collections 的 ChainMap 來 達到相同的目的 60
  60. 60. • 如果透過 ChainMap 指定更新某對鍵值, 會在底層中第一個找到鍵的 dict 中更新對 應的值 • 若底層全部的 dict 都找不到對應的鍵時, 就會直接在第一個 dict 新增鍵值 61
  61. 61. • ChainMap 底層維護的 list,可以透過 maps 屬性來取得 62
  62. 62. • new_child() 方法可以指定dict,這會 建立一個新的 ChainMap,當中來源 ChainMap 中的 dict 並包含指定的 dict • 如果想建立新 ChainMap,不包含來源 ChainMap 的第一個 dict,可以使用 parents 屬性 63
  63. 63. • 想要實現 [] 取值,可以實作 __getitem__() • 想要實現 [] 設值, 可以實作 __setitem__() • 若想透過del 與 [] 來刪除, 可以實作 __delitem__() 64
  64. 64. 65
  65. 65. 66
  66. 66. • collections.abc 模組中提供了許多實 作群集時的基礎類別 • 開發者繼承這些類別,可以避免遺忘了必 須實作的方法,也可以有一些基本的共用 實作 67
  67. 67. • 方才自行實作的 ChainMap,可以改繼承 MutableMapping,以更符合 dict 的物 件協定: 68
  68. 68. 69
  69. 69. 70
  70. 70. • Mapping 並不是 dict 的子類別,只是擁 有 dict 的行為 • Sequence 也不是 list 的子類別,只是 擁有 list 的行為 • Set 也不是 set 的子類別,只是擁有 set 的行為 71
  71. 71. • 只是想要基於 str、list、dict 等行為,增 加一些自定義方法,可以使用 collections 的 UserString、UserList、UserDict 72
  72. 72. 73

×