[注意]
- 本文假設你已經寫過一點 Python,並且有基礎的物件導向 (object-oriented, OO) 觀念,至少要知道什麼是 class 跟 instance。
- 本文只討論 Python 3,至於 Python 2 那種早該被歷史淘汰的該死東西將完全不去鳥它。
- 這篇只是筆記性質的虎頭蛇尾的半廢物文章,寫到後來就忘在硬碟裡,只是今天 [2016-08-28 日 23:55] 不小心把這篇 deply 出來就想說…算了出來就出來吧
_(:3」∠ )_
,但現在沒那心情所以也懶得仔細再看一次科科,本文最後的 singleton 範例有些東西我自己也搞不清楚了,知道的大大敬請指教<(_ _)>
要理解 Python 的 Meta programming,必須同時理解 object
, type
以及 __metaclass__
, __call__
, __new__
, __init__
的運作機制。
Python 中的 object
- 首先我們必須先牢牢記住一個重要觀念:Python 是一種物件導向語言;在 Python 裡面,所有你能想得到的東西都是 object。
- 我們可以用
type()
這個內建函數,來得知某樣東西的 type。- 給
type()
一個 object 時,會回傳一個東西叫做Type Object
,你可以用print()
印出來看看是什麼樣子:
- 給
1 | print( type(1) ) # <class 'int'> |
- 上面的例子說明了,像
"hello"
這個字串,在 Python 中其實是str
這個class
的 instance。 - 連函數(function)也是一個 object:
1 | def func(): |
那我定義一個 class 的話,該 class 的 type 又是什麼?建立出來的 instance 的 type 又是什麼?我上面沒寫,因為這個問題的答案很違反直覺,下面就要來解釋。
Python 中的 class
一般來說,物件導向語言中的「class」是用來「描述如何建立 object」的程式碼;我們寫 class 就是為了建立 object。然而在 Python 中:
- 連 class 本身也是 object
- class 是 meta class 的 instance。
- meta class 是 class 的 class。
當你一寫下 class
關鍵字 ,Python 會執行它,並建立一個 class object
- 這個 class object 並不是 class instance,而是 class 自己本身。
- 這個 class object 的功能就是建立自己的 instance object。
[注意]
為了避免混淆,接下來提到的所有 class object 指的皆為 「class 本身的 object」,而不是 class instance object。
class object
既然 Python 的 class 自己也是 object,也就是說你可以把 class object :
- assign 給 variable
- copy 它
- 增加 attributes
- 當作 function parameter 來傳遞
前面提到的 type()
這內建函數極度詭異,當塞三個參數進去時,他的功能會變成建立 class object…怎麼做呢?官方文件是這樣寫:
type(name, bases, dict)
分別對應到 class attributes 中的:
name
會變成__name__
,也就是 class 的名稱bases
會變成__bases__
,也就是該 class 要繼承自哪些 base classdict
會變成__dict__
,也就是該 class 所有的 member
1 | # 手動寫法 (用 class 關鍵字) =================================================== |
這兩種寫法的意義是完全相同的,真是他媽的莫名其妙對吧。分析一下上面這個鬼打牆的範例:
Hello
(class object) 就是 class 自己本身的 object。<class '__main__.Hello'>
Hello()
(class instance object) 就是大家都知道的 instance 沒啥好說的。- 透過
type()
可以得知一個 object 的 type:Hello()
因為是 instance,很合理的 type 就是 class object<class '__main__.Hello'>
Hello
是 class object,那他的 type 呢?嗯,真是靠北,就是type
,也就是<class 'type'>
那還有個問題: type
自己本身的 type 是什麼?
1 | print( type(Hello) ) # <class 'type'> |
__class__
str
這個 class 建立所有的 string objectint
這個 class 建立所有的 int objecttype
這個 class 建立了所有的 class object
透過 __class__
這個特殊 attribute,可以得知一個 object 是什麼 class 的 instance:
1 | title = "The C++ Programming Language" |
那…來看看這些 object 的 .__class__.__class__
又是什麼
1 | print(title.__class__.__class__) # <class 'type'> |
嗯嗯,Python 裡面所有的 class 都是 type
的 instance。
Metaclass
metaclass 是 class 的 class,也就是說:
object 是 class 的 instance
class 是 metaclass 的 instance
type
type
是 Python 中的 metaclass:
type
本身也是一個 class
type
本身的 metaclass 就是他自己
要寫一個 metaclass 的話,就繼承 type
__call__()
預設會呼叫 __new__()
跟 __init__()
call
來釐清一下:
1 | class Hello: |
Python 在實體化 Hello
時的過程:
Hello()
↓
等同呼叫 Hello.__call__()
↓
呼叫 Hello.__new__() 建立出 object 並回傳該 object
↓
再呼叫 Hello.__init__() 來讓該 object 初始化其他有的沒的
__call__()
在 class 中的預設行為,就是依序幫你呼叫 __new__()
跟 __init__()
。
最後整理
假設我們定義了一個 class 叫 Hello
__call__
定義了當Hello
後面被加上小括號、當作 function 來呼叫時的行為。預設行為是依序呼叫__new__()
跟__init__()
__new__
定義了Hello
如何實體化,最後會回傳一個實體 object。__init__
定義了Hello
實體化後,其實體 object 如何初始化(例如 member variable 定義之類的,這是大家最熟悉的部份)。
Singleton
嘗試一:透過 __new__
1 | class Single(object): |
嘗試二:透過 metaclass
還記得self
只是約定成俗的東西、其實你要寫啥都可以吧? cls
就是這樣的存在。Python 大家都習慣用 cls
當作指向 class 的變數名稱、並用 self
當作指向 instance 的變數名稱。
1 | class Singleton(type): |
id 不同,為什麼?
如果第 5 行不加上
cls
,寫成super().__new__(*args, **kwargs)
會爆掉:TypeError: type.__new__(X): X is not a type object (str)
為什麼?
改從 __call__
下手
1 | class Singleton(type): |