Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.

6. 類別的繼承

瞭解繼承目的
認識鴨子定型
重新定義方法
認識 object
建立、尋找文件資源
泛型入門

  • Identifiez-vous pour voir les commentaires

  • Soyez le premier à aimer ceci

6. 類別的繼承

  1. 1. 6. 類別的繼承 • 學習目標 – 瞭解繼承目的 – 認識鴨子定型 – 重新定義方法 – 認識 object – 建立、尋找文件資源 – 泛型入門 2
  2. 2. 繼承共同行為 3
  3. 3. 4
  4. 4. • 重複在程式設計上,就是不好的訊號 5
  5. 5. 6
  6. 6. 鴨子定型 7
  7. 7. • 動態定型語言界流行的鴨子定型 – 如果它走路像個鴨子,游泳像個鴨子,叫聲像 個鴨子,那它就是鴨子。 • 思考物件的行為,而不是物件的種類 • 具有比較高的通用性 8
  8. 8. 重新定義方法 • 在多數的情況下,檢查型態而給予不同的 流程行為,對於程式的維護性有著不良的 影響,應該避免: 9
  9. 9. • 在繼承後若打算基於父類別的方法實作來 重新定義某個方法,可以使用 super() 來 呼叫父類別方法: 10
  10. 10. 11
  11. 11. 定義抽象方法 • 如果希望子類別在繼承之後,一定要實作 的方法 – 在父類別中指定 metaclass 為 abc 模組的 ABCMeta 類別 – 在指定的方法上標註 abc 模組的 @abstractmethod 來達到需求 12
  12. 12. 13
  13. 13. • 如上定義就不能使用 Role 來建構物件了,否 則會發生 TypeError • 若類別繼承了 Role 類別,沒有實作fight() 方法,在實例化時也會發生 TypeError: 14
  14. 14. 初識 object 與 super() • 若沒有指定父類別,那麼就是繼承 object 類別 15
  15. 15. • 若沒有定義的方法,某些場合下必須呼叫 時,就會看看父類別中是否有定義 • 如果定義了自己的方法,那麼就會以你定 義的為主,不會主動呼叫父類別的方法 16
  16. 16. 17
  17. 17. 18
  18. 18. Rich comparison 方法 • object 類別定義了__lt__()、 __le__()、__eq__()、__ne__()、 __gt__()、__ge__() • 定義了物件之間使用<、<=、==、!=、>、 >=等比較時,應該要有的比較結果 19
  19. 19. • 想要能使用==來比較兩個物件是否相等, 必須定義 __eq__() 方法 • __ne__() 預設會呼叫 __eq__() 並反 相其結果 • object 定義的 __eq__() 方法,預設 是使用 is 來比較兩個物件 20
  20. 20. 21
  21. 21. • 實作 __eq__() 時通常也會實作 __hash__() • __lt__() 與 __gt__() 互補,而 __le__() 與 __ge__() 互補 • 基本上只要定義 __gt__()、__ge__() 就可以 22
  22. 22. 23
  23. 23. • 真的需要定義這整組方法的行為,可以使 用 functools.total_ordering 24
  24. 24. 使用 enum 列舉 • 透過 dict 列舉: 25
  25. 25. • 透過類別列舉: 26
  26. 26. • 從 Python 3.4 開始新增了 enum 模組 27
  27. 27. • 列舉物件上具有 name 與 value,可用來 取得列舉名稱與列舉值 • 也可以使用 [] 指定列舉名稱取得列舉物件。 28
  28. 28. • 可以使用 for in 來迭代列舉: • 繼承 Enum 或 IntEnum 類別定義列舉時,列 舉名稱不得重複,然而,列舉值可以重複。 29
  29. 29. 30
  30. 30. • 如果想要在列舉時值不得重複,可以在類 別上加註 enum 模組的 @unique 31
  31. 31. 多重繼承 • 可以進行多重繼承,也就是一次繼承兩個 父類別的程式碼定義 • 父類別之間使用逗號作為區隔 32
  32. 32. 33
  33. 33. • 如果繼承時多個父類別中有相同的方法名 稱,就要注意搜尋的順序 • 基本上是從子類別開始尋找名稱,接著是 同階層父類別由左至右搜尋,再至更上層 • 同一階層父類別由左至右搜尋,直到達到 頂層為止 34
  34. 34. 35
  35. 35. • 一個子類別在尋找指定的屬性或方法名稱 時,會依據類別的 __mro__ 屬性的 tuple 中元素順序尋找 • MRO 全名是 Method Resolution Order, • 如果想要知道直接父類別的話,則可以透 過類別的__bases__來得知 36
  36. 36. 37
  37. 37. • __mro__ 是唯讀屬性 • 改變 __bases__ 來改變直接父類別,從而 使得 __mro__ 的內容也跟著變動 38
  38. 38. • 如果定義類別時,python 直譯器無法生成 __mro__,會引發 TypeError 39
  39. 39. • 子類別繼承兩個父類別的順序,會決定抽 象方法是否得到實作 • 判定一個抽象方法是否有實作,也是依照 __mro__中類別的順序 40
  40. 40. 41
  41. 41. 建立 ABC • 多重繼承的能力,通常建議只用來繼承 ABC,也就是抽象基礎類別 • 一個抽象基礎類別,不會定義屬性,也不 會有 __init__() 定義 42
  42. 42. • 來考慮一個 Ball 類別 43
  43. 43. 44
  44. 44. 45
  45. 45. 使用final • Python 3.8以後,如果想限定某類別在繼 承體系中是最後一個 46
  46. 46. • 定義方法時也可以使用final裝飾器,表 示最後一次定義該方法 47
  47. 47. 探討 super() • 無引數 super()呼叫,是 super(__class__, <first argument>) 的簡便方法 • 在一個綁定方法中,就相當於使用 super(__class__, self) • 在 @classmethod 標註的方法中,就相 當於呼叫super(__class__, clz)。 48
  48. 48. 49
  49. 49. 50
  50. 50. • 呼叫 super(type, obj) 時,會使用 obj 的類別之 __mro__ 清單 • 從指定的 type 之下個類別開始查找,看 看是否有指定的方法 – 若有的話,將 obj 當作是呼叫方法的首引數 51
  51. 51. 52
  52. 52. • 呼叫 super(type, type2) 時,會使 用 type2 的 __mro__ 清單 • 從指定的 type 之下個類別開始查找,看 看是否有指定的方法,若有的話,將 type2 當作是呼叫方法的第一個引數 53
  53. 53. 54
  54. 54. • @staticmethod 標註的方法呢? 55
  55. 55. DocStrings • 標準程式庫原始碼本身就附有文件 56
  56. 56. • 想為自訂函式定義 DocStrings: • 在函式、類別或模組定義的一開頭,使用 ''' 包括起來的多行字串,會成為函式、 類別或模組的 __doc__ 屬性值 57
  57. 57. 58
  58. 58. • 慣例上,單行的 DocStrings 會是在一行中 使用 ''' 左右含括起來 • 函式或方法中的 DocStrings 若是多行字串, ''' 緊接的第一行,會是函式的簡短描述 • 之後空一行後,才是參數或其他相關說明, 最後換一行並縮排結束 59
  59. 59. 60
  60. 60. • 如果是類別或模組的多行 DocStrings,會 是在 ''' 後馬上換行,以相同層次縮排 61
  61. 61. 62
  62. 62. • 如果想針對套件來撰寫 DocStrings 63
  63. 63. 64
  64. 64. 65
  65. 65. 查詢官方文件 66
  66. 66. 67
  67. 67. 68
  68. 68. 泛型入門 • 若開始考慮到4.3.4中的一些因素,或者其 他工程上的考量,而開始使用型態提示, 後續也許就會開始考慮泛型 69
  69. 69. • 希望其他開發者呼叫 first() 時只傳入 list • 異質型態? • 定義佔位型態 T: 70
  70. 70. • 想限制 T 實際的型態都只能是 int,或者 都是 str: 71
  71. 71. 定義泛型類別 • 可以放置的水果種類沒有限制 72
  72. 72. • 定義泛型類別 73
  73. 73. • 在定義泛型類別時,可以使用的型態佔位 名稱,並不限於一個 74
  74. 74. • 如果在使用時不指定佔位型態 T 實際之型 態,會使用 typing 模組的 Any 型態,而 不是 object • 前者可以支援鴨子定型,後者就真的限定 為 object error: "object" has no attribute "upper" 75

×