SlideShare a Scribd company logo
1 of 77
Download to read offline
14. 進階主題
• 學習目標
– 運用描述器
– 實作裝飾器
– 定義 meta 類別
– 使用相對匯入
– 泛型進階
2
描述器
• 擁有 __get__() 方法,以及選擇性的
__set__()、__delete__() 方法
• 當描述器成為某個類別的屬性成員時,對
於類別屬性或者其實例屬性的取得、設定
或刪除,將會交由描述器來決定如何處理
3
4
• 當 Descriptor 被指定給 Some 類別的 x
屬性時,對於 Some 實例 s 的屬性取值、
指定或刪除,分別相當於進行了以下動作:
• 對於 Some.x 這個取值動作,則相當於:
5
6
7
• 資料描述器可以攔截對實例的屬性取得、
設定與刪除行為
• 非資料描述器,是用來攔截透過實例取得
類別屬性時的行為
8
9
10
• 若想控制可以指定給物件的屬性名稱,可
以在定義類別時指定 __slots__
• 這個屬性要是個字串清單,列出可指定給
物件的屬性名稱
11
12
• 如果類別定義時指定了 __slots__,那麼
從類別建構出來的實例就不會具有
__dict__ 屬性
13
14
• __slots__ 中的屬性,Python 會將之實
作為描述器
15
• __slots__ 屬性最好作為類別屬性來使用
• 父類別中定義的 __slots__,僅可以透過
父類別來取得,而子類別的 __slots__ 則
僅可以透過子類別來取得
16
• 若父類別中沒有定義 __slots__,子類別
即使定義了__slots__,以子類別建構出
來的實例,仍然會具有 __dict__ 屬性
17
• 如果父類別定義了__slots__,而子類別
沒有定義自己的 __slots__,子類別建構
出來的實例也會有 __dict__
18
• 物件本身可以決定存取屬性的行為
• __getattribute__() 一但定義,任何
屬性的尋找都會被攔截,即使是那些
__xxx__ 的內建屬性名稱
• __getattr__() 的作用,是作為尋找屬
性的最後一個機會
19
• 取得屬性的順序
– 實例的 __getattribute__()
– 資料描述器的 __get__()
– 實例的 __dict__
– 非資料描述器的 __get__()
– 實例的 __getattr__()
20
• __setattr__() 的作用,在於攔截所有
對實例的屬性設定
• 設定屬性順序記憶
– 實例的 __setattr__()
– 資料描述器的 __set__()
– 實例的 __dict__
21
• __delattr__()的作用,在於攔截所有對
實例的屬性設定
• 刪除屬性順序記憶
– 實例的__delattr__()
– 資料描述器的__delete__()
– 實例的__dict__
22
函式裝飾器
• 裝飾器本質上就是一個函式可接受函式且
傳回函式
• 假設你設計了一個點餐程式…
23
• 一個函式可以接受函式並傳回函式
24
25
26
27
• 如果裝飾器語法需要帶有參數,用來作為
裝飾器的函式,必須先以指定的參數執行
一次,傳回函式物件再來裝飾指定的函式
28
29
30
• 除了對函式進行裝飾之外,也可以對類別
作裝飾,也就是所謂類別裝飾器
31
• 如果將經過裝飾的 friedchicken() 函式
本身 print() 出來,會顯示什麼呢?
32
33
• 若函式接受類別並傳回類別時,就可設計
為類別裝飾器,以用來標註類別
34
35
• 對類別上定義之方法進行裝飾自然也是可
行的
• 若是實例方法,傳回的函式,第一個參數
是用來接受類別的實例
36
37
38
• 除了使用函式來定義裝飾器之外,也可以
使用類別來定義裝飾器
39
• 若要使用類別來定義函式裝飾器:
40
• 若最後 some 參考之實例,想偽裝為被裝飾
前的函式
41
42
43
44
認識 type 類別
• 每個物件實例本身都有個 __class__ 屬性
• 類別本身也有個 __class__ 屬性
45
• 在類別上呼叫 __call__() 會如何呢?
46
• 使用 type 類別建構類別時,必須指定三個
引數
– 類別名稱(字串)
– 類別的父類別(tuple)
– 類別的屬性(dict)
47
• 物件是類別的實例,而類別是 type 的實例
• 如果有方法能介入 type 建立實例與初始化
的過程,就會有辦法改變類別的行為,這
就是 meta 類別的基本概念
48
• type 是個類別,那麼可以繼承嗎?
49
• 可以在使用 class 定義類別時,指定
metaclass 為 SomeMeta:
50
• 繼承了 type 的類別可以作為 meta 類別
• metaclass 是個協定
• 若指定了 metaclass 的類別, Python 在
剖析完類別定義後, 會使用指定的
metaclass 來進行類別的建構與初始化
51
• 如果使用 class 定義類別時繼承某個父類
別,亦想要指定 metaclass
• 使用類別建立物件時:
52
• 若想改變一個類別建立實例與初始化的流
程,則可以在定義 meta 類別時定義
__call__()方法:
53
• meta 類別就是 type 的子類別
• 藉由 metaclass = MetaClass 的協定,
可在類別定義剖析完後,繞送至指定的
meta 類別
• 可以定義 meta 類別的 __new__()方法,
決定類別如何建立
– 定義 meta 類別的 __init__(),可以決定類
別如何初始
– 定義 meta 類別的__call__()方法,決定若
使用類別來建構物件時,該如何進行物件的建
立與初始
54
• metaclass 並不僅僅可指定類別
• 可以指定的對象可以是類別、函式或任何
的物件,只要它具有 __call__() 方法
55
56
• 可以定義類別的 __abstractmethods__,
指明某些特性是抽象方法
57
• 子類別不會看的到父類別的
__abstractmethods__
58
59
60
• Python 實際上還支援相對匯入(Relative
import)
• 如果想在 xyz.py 中匯入 abc 模組,在
xyz.py 中不能寫 import abc,在
Python 3 中這會是絕對匯入
• 實際上會匯入的是標準程式庫的 abc 模組
61
• 如果想在 xyz.py 中匯入 mno 模組,在
xyz.py 中不能寫 import mno
• 這會引發 ImportError,指出沒有 mno
這個模組
• 如果要使用絕對匯入,必須撰寫 import
pkg1.mno
• 若要使用相對匯入,則可以撰寫 from .
import mno
• 如果想使用的是 mno 模組中的 foo()函式,
使用相對匯入的話,還可以撰寫
from .mno import foo 這樣的方式
62
• 在某個程式中,若 import pkg1 的話,
會執行__init__.py 的內容
• 可以在 pkg1 的 __init__.py 中撰寫:
• 只要 import pkg1,就可以直接使用
pkg1.abc、pkg2.mno、pkg1.xyz 來使
用模組了
63
• 如果想要 import pkg1 之後,可以直接
使用 pkg1.abc、pkg2.mno、pkg1.xyz
• 還能直接使用 pkg1.sub_pkg.foo、
pkg1.sub_pkg.orz 模組
64
• 那麼在 pkg1 的 __init__.py 中,可以撰寫:
• 而在 pkg1.sub_pkg 的 __init__.py 中,可
以撰寫:
65
• 相對匯入只能用在套件之中,如果試圖使
用 python 直譯器執行的某個模組中含有
相對匯入,會引發 SystemError
66
型態邊界
• 可以指定 bound 來定義型態的邊界
67
68
共變性
69
• 如果 B 是 A 的子類別,而 Node[B] 可視為
一種 Node[A],則稱 Node 具有共變性或
有彈性的(flexible)
• 使用 TypeVar 建立的佔位型態預設為不可
變的(Nonvariant),然而,可藉由
covariant 為 True 來支援共變性
70
71
72
• 在支援共變性的情況下,若使用工具於靜
態時期檢查型態正確性時,要留意底下的
問題:
73
逆變性
• 如果 B 是 A 的子類別,如果 Node[A] 視為
一種 Node[B],則稱 Node 具有逆變性
(Contravariance)
• 可藉由 contravariant 為 True 來支援
逆變性
74
• 希望使用 List[Fruit] 來收集全部籃子
的水果,然後依重量排序呢?
75
76
77

More Related Content

What's hot

深入模組化
深入模組化深入模組化
深入模組化Justin Lin
 
Java SE 8 技術手冊第 17 章 - 反射與類別載入器
Java SE 8 技術手冊第 17 章 - 反射與類別載入器Java SE 8 技術手冊第 17 章 - 反射與類別載入器
Java SE 8 技術手冊第 17 章 - 反射與類別載入器Justin Lin
 
[圣思园][Java SE]Reflection
[圣思园][Java SE]Reflection[圣思园][Java SE]Reflection
[圣思园][Java SE]ReflectionArBing Xie
 
資料永續與交換
資料永續與交換資料永續與交換
資料永續與交換Justin Lin
 
5. 建構式、原型與類別
5. 建構式、原型與類別5. 建構式、原型與類別
5. 建構式、原型與類別Justin Lin
 
CH09:Collection與Map
CH09:Collection與MapCH09:Collection與Map
CH09:Collection與MapJustin Lin
 
Python面向对象开发基础篇
Python面向对象开发基础篇Python面向对象开发基础篇
Python面向对象开发基础篇modou li
 
Java SE 7 技術手冊投影片第 09 章 - Collection與Map
Java SE 7 技術手冊投影片第 09 章 - Collection與MapJava SE 7 技術手冊投影片第 09 章 - Collection與Map
Java SE 7 技術手冊投影片第 09 章 - Collection與MapJustin Lin
 
10. 資料永續與交換
10. 資料永續與交換10. 資料永續與交換
10. 資料永續與交換Justin Lin
 
CH16:整合資料庫
CH16:整合資料庫CH16:整合資料庫
CH16:整合資料庫Justin Lin
 
Java SE 8 技術手冊第 5 章 - 物件封裝
Java SE 8 技術手冊第 5 章 - 物件封裝Java SE 8 技術手冊第 5 章 - 物件封裝
Java SE 8 技術手冊第 5 章 - 物件封裝Justin Lin
 
從模組到類別
從模組到類別從模組到類別
從模組到類別Justin Lin
 
Java SE 7 技術手冊投影片第 15 章 - 反射器與類別載入器
Java SE 7 技術手冊投影片第 15 章 - 反射器與類別載入器Java SE 7 技術手冊投影片第 15 章 - 反射器與類別載入器
Java SE 7 技術手冊投影片第 15 章 - 反射器與類別載入器Justin Lin
 
CH04:認識物件
CH04:認識物件CH04:認識物件
CH04:認識物件Justin Lin
 
Java SE 7 技術手冊投影片第 11 章 - 執行緒與並行API
Java SE 7 技術手冊投影片第 11 章 - 執行緒與並行APIJava SE 7 技術手冊投影片第 11 章 - 執行緒與並行API
Java SE 7 技術手冊投影片第 11 章 - 執行緒與並行APIJustin Lin
 
11. DOM、事件與樣式
11. DOM、事件與樣式11. DOM、事件與樣式
11. DOM、事件與樣式Justin Lin
 
10, inner classes
10, inner classes10, inner classes
10, inner classested-xu
 
《Python 3.5 技術手冊》第六章草稿
《Python 3.5 技術手冊》第六章草稿《Python 3.5 技術手冊》第六章草稿
《Python 3.5 技術手冊》第六章草稿Justin Lin
 
Java SE 7 技術手冊投影片第 14 章 - 整合資料庫
Java SE 7 技術手冊投影片第 14 章 - 整合資料庫Java SE 7 技術手冊投影片第 14 章 - 整合資料庫
Java SE 7 技術手冊投影片第 14 章 - 整合資料庫Justin Lin
 

What's hot (20)

深入模組化
深入模組化深入模組化
深入模組化
 
Java SE 8 技術手冊第 17 章 - 反射與類別載入器
Java SE 8 技術手冊第 17 章 - 反射與類別載入器Java SE 8 技術手冊第 17 章 - 反射與類別載入器
Java SE 8 技術手冊第 17 章 - 反射與類別載入器
 
[圣思园][Java SE]Reflection
[圣思园][Java SE]Reflection[圣思园][Java SE]Reflection
[圣思园][Java SE]Reflection
 
資料永續與交換
資料永續與交換資料永續與交換
資料永續與交換
 
進階主題
進階主題進階主題
進階主題
 
5. 建構式、原型與類別
5. 建構式、原型與類別5. 建構式、原型與類別
5. 建構式、原型與類別
 
CH09:Collection與Map
CH09:Collection與MapCH09:Collection與Map
CH09:Collection與Map
 
Python面向对象开发基础篇
Python面向对象开发基础篇Python面向对象开发基础篇
Python面向对象开发基础篇
 
Java SE 7 技術手冊投影片第 09 章 - Collection與Map
Java SE 7 技術手冊投影片第 09 章 - Collection與MapJava SE 7 技術手冊投影片第 09 章 - Collection與Map
Java SE 7 技術手冊投影片第 09 章 - Collection與Map
 
10. 資料永續與交換
10. 資料永續與交換10. 資料永續與交換
10. 資料永續與交換
 
CH16:整合資料庫
CH16:整合資料庫CH16:整合資料庫
CH16:整合資料庫
 
Java SE 8 技術手冊第 5 章 - 物件封裝
Java SE 8 技術手冊第 5 章 - 物件封裝Java SE 8 技術手冊第 5 章 - 物件封裝
Java SE 8 技術手冊第 5 章 - 物件封裝
 
從模組到類別
從模組到類別從模組到類別
從模組到類別
 
Java SE 7 技術手冊投影片第 15 章 - 反射器與類別載入器
Java SE 7 技術手冊投影片第 15 章 - 反射器與類別載入器Java SE 7 技術手冊投影片第 15 章 - 反射器與類別載入器
Java SE 7 技術手冊投影片第 15 章 - 反射器與類別載入器
 
CH04:認識物件
CH04:認識物件CH04:認識物件
CH04:認識物件
 
Java SE 7 技術手冊投影片第 11 章 - 執行緒與並行API
Java SE 7 技術手冊投影片第 11 章 - 執行緒與並行APIJava SE 7 技術手冊投影片第 11 章 - 執行緒與並行API
Java SE 7 技術手冊投影片第 11 章 - 執行緒與並行API
 
11. DOM、事件與樣式
11. DOM、事件與樣式11. DOM、事件與樣式
11. DOM、事件與樣式
 
10, inner classes
10, inner classes10, inner classes
10, inner classes
 
《Python 3.5 技術手冊》第六章草稿
《Python 3.5 技術手冊》第六章草稿《Python 3.5 技術手冊》第六章草稿
《Python 3.5 技術手冊》第六章草稿
 
Java SE 7 技術手冊投影片第 14 章 - 整合資料庫
Java SE 7 技術手冊投影片第 14 章 - 整合資料庫Java SE 7 技術手冊投影片第 14 章 - 整合資料庫
Java SE 7 技術手冊投影片第 14 章 - 整合資料庫
 

Similar to 進階主題

Programming python - part 2
Programming python - part 2Programming python - part 2
Programming python - part 2Che-Cheng Hsu
 
Java SE 7 技術手冊投影片第 16 章 - 自訂泛型、列舉與標註
Java SE 7 技術手冊投影片第 16 章 - 自訂泛型、列舉與標註Java SE 7 技術手冊投影片第 16 章 - 自訂泛型、列舉與標註
Java SE 7 技術手冊投影片第 16 章 - 自訂泛型、列舉與標註Justin Lin
 
Java SE 7 技術手冊投影片第 05 章 - 物件封裝
Java SE 7 技術手冊投影片第 05 章  - 物件封裝Java SE 7 技術手冊投影片第 05 章  - 物件封裝
Java SE 7 技術手冊投影片第 05 章 - 物件封裝Justin Lin
 
Java SE 7 技術手冊投影片第 04 章 - 認識物件
Java SE 7 技術手冊投影片第 04 章 - 認識物件Java SE 7 技術手冊投影片第 04 章 - 認識物件
Java SE 7 技術手冊投影片第 04 章 - 認識物件Justin Lin
 
2, object oriented programming
2, object oriented programming2, object oriented programming
2, object oriented programmingted-xu
 
Java SE 7 技術手冊投影片第 06 章 - 繼承與多型
Java SE 7 技術手冊投影片第 06 章 - 繼承與多型Java SE 7 技術手冊投影片第 06 章 - 繼承與多型
Java SE 7 技術手冊投影片第 06 章 - 繼承與多型Justin Lin
 
flagboot learning framework technology sharing
flagboot learning framework technology sharingflagboot learning framework technology sharing
flagboot learning framework technology sharingxastraxastra
 

Similar to 進階主題 (9)

Programming python - part 2
Programming python - part 2Programming python - part 2
Programming python - part 2
 
Java SE 7 技術手冊投影片第 16 章 - 自訂泛型、列舉與標註
Java SE 7 技術手冊投影片第 16 章 - 自訂泛型、列舉與標註Java SE 7 技術手冊投影片第 16 章 - 自訂泛型、列舉與標註
Java SE 7 技術手冊投影片第 16 章 - 自訂泛型、列舉與標註
 
组合、备忘录、建造者模式、原型
组合、备忘录、建造者模式、原型组合、备忘录、建造者模式、原型
组合、备忘录、建造者模式、原型
 
Java SE 7 技術手冊投影片第 05 章 - 物件封裝
Java SE 7 技術手冊投影片第 05 章  - 物件封裝Java SE 7 技術手冊投影片第 05 章  - 物件封裝
Java SE 7 技術手冊投影片第 05 章 - 物件封裝
 
Java SE 7 技術手冊投影片第 04 章 - 認識物件
Java SE 7 技術手冊投影片第 04 章 - 認識物件Java SE 7 技術手冊投影片第 04 章 - 認識物件
Java SE 7 技術手冊投影片第 04 章 - 認識物件
 
SCJP ch09
SCJP ch09SCJP ch09
SCJP ch09
 
2, object oriented programming
2, object oriented programming2, object oriented programming
2, object oriented programming
 
Java SE 7 技術手冊投影片第 06 章 - 繼承與多型
Java SE 7 技術手冊投影片第 06 章 - 繼承與多型Java SE 7 技術手冊投影片第 06 章 - 繼承與多型
Java SE 7 技術手冊投影片第 06 章 - 繼承與多型
 
flagboot learning framework technology sharing
flagboot learning framework technology sharingflagboot learning framework technology sharing
flagboot learning framework technology sharing
 

More from Justin Lin

Ch14 簡介 Spring Boot
Ch14 簡介 Spring BootCh14 簡介 Spring Boot
Ch14 簡介 Spring BootJustin Lin
 
Ch13 整合 Spring MVC/Security
Ch13 整合 Spring MVC/SecurityCh13 整合 Spring MVC/Security
Ch13 整合 Spring MVC/SecurityJustin Lin
 
Ch12 Spring 起步走
Ch12 Spring 起步走Ch12 Spring 起步走
Ch12 Spring 起步走Justin Lin
 
Ch11 簡介 JavaMail
Ch11 簡介 JavaMailCh11 簡介 JavaMail
Ch11 簡介 JavaMailJustin Lin
 
Ch10 Web 容器安全管理
Ch10 Web 容器安全管理Ch10 Web 容器安全管理
Ch10 Web 容器安全管理Justin Lin
 
Ch09 整合資料庫
Ch09 整合資料庫Ch09 整合資料庫
Ch09 整合資料庫Justin Lin
 
Ch08 自訂標籤
Ch08 自訂標籤Ch08 自訂標籤
Ch08 自訂標籤Justin Lin
 
Ch07 使用 JSTL
Ch07 使用 JSTLCh07 使用 JSTL
Ch07 使用 JSTLJustin Lin
 
Ch06 使用 JSP
Ch06 使用 JSPCh06 使用 JSP
Ch06 使用 JSPJustin Lin
 
Ch05 Servlet 進階 API、過濾器與傾聽器
Ch05 Servlet 進階 API、過濾器與傾聽器Ch05 Servlet 進階 API、過濾器與傾聽器
Ch05 Servlet 進階 API、過濾器與傾聽器Justin Lin
 
Ch04 會話管理
Ch04 會話管理Ch04 會話管理
Ch04 會話管理Justin Lin
 
Ch03 請求與回應
Ch03 請求與回應Ch03 請求與回應
Ch03 請求與回應Justin Lin
 
Ch02 撰寫與設定 Servlet
Ch02 撰寫與設定 ServletCh02 撰寫與設定 Servlet
Ch02 撰寫與設定 ServletJustin Lin
 
CH1. 簡介 Web 應用程式
CH1. 簡介 Web 應用程式CH1. 簡介 Web 應用程式
CH1. 簡介 Web 應用程式Justin Lin
 
13.並行、平行與非同步
13.並行、平行與非同步13.並行、平行與非同步
13.並行、平行與非同步Justin Lin
 
12. 除錯、測試與效能
12. 除錯、測試與效能12. 除錯、測試與效能
12. 除錯、測試與效能Justin Lin
 
11. 常用內建模組
11. 常用內建模組11. 常用內建模組
11. 常用內建模組Justin Lin
 
8. open() 與 io 模組
8. open() 與 io 模組8. open() 與 io 模組
8. open() 與 io 模組Justin Lin
 
7. 例外處理
7. 例外處理7. 例外處理
7. 例外處理Justin Lin
 
6. 類別的繼承
6. 類別的繼承6. 類別的繼承
6. 類別的繼承Justin Lin
 

More from Justin Lin (20)

Ch14 簡介 Spring Boot
Ch14 簡介 Spring BootCh14 簡介 Spring Boot
Ch14 簡介 Spring Boot
 
Ch13 整合 Spring MVC/Security
Ch13 整合 Spring MVC/SecurityCh13 整合 Spring MVC/Security
Ch13 整合 Spring MVC/Security
 
Ch12 Spring 起步走
Ch12 Spring 起步走Ch12 Spring 起步走
Ch12 Spring 起步走
 
Ch11 簡介 JavaMail
Ch11 簡介 JavaMailCh11 簡介 JavaMail
Ch11 簡介 JavaMail
 
Ch10 Web 容器安全管理
Ch10 Web 容器安全管理Ch10 Web 容器安全管理
Ch10 Web 容器安全管理
 
Ch09 整合資料庫
Ch09 整合資料庫Ch09 整合資料庫
Ch09 整合資料庫
 
Ch08 自訂標籤
Ch08 自訂標籤Ch08 自訂標籤
Ch08 自訂標籤
 
Ch07 使用 JSTL
Ch07 使用 JSTLCh07 使用 JSTL
Ch07 使用 JSTL
 
Ch06 使用 JSP
Ch06 使用 JSPCh06 使用 JSP
Ch06 使用 JSP
 
Ch05 Servlet 進階 API、過濾器與傾聽器
Ch05 Servlet 進階 API、過濾器與傾聽器Ch05 Servlet 進階 API、過濾器與傾聽器
Ch05 Servlet 進階 API、過濾器與傾聽器
 
Ch04 會話管理
Ch04 會話管理Ch04 會話管理
Ch04 會話管理
 
Ch03 請求與回應
Ch03 請求與回應Ch03 請求與回應
Ch03 請求與回應
 
Ch02 撰寫與設定 Servlet
Ch02 撰寫與設定 ServletCh02 撰寫與設定 Servlet
Ch02 撰寫與設定 Servlet
 
CH1. 簡介 Web 應用程式
CH1. 簡介 Web 應用程式CH1. 簡介 Web 應用程式
CH1. 簡介 Web 應用程式
 
13.並行、平行與非同步
13.並行、平行與非同步13.並行、平行與非同步
13.並行、平行與非同步
 
12. 除錯、測試與效能
12. 除錯、測試與效能12. 除錯、測試與效能
12. 除錯、測試與效能
 
11. 常用內建模組
11. 常用內建模組11. 常用內建模組
11. 常用內建模組
 
8. open() 與 io 模組
8. open() 與 io 模組8. open() 與 io 模組
8. open() 與 io 模組
 
7. 例外處理
7. 例外處理7. 例外處理
7. 例外處理
 
6. 類別的繼承
6. 類別的繼承6. 類別的繼承
6. 類別的繼承
 

進階主題