元類相關(type & metaclass)
"""
metaclass作用:
1) 攔截類的創建
2) 修改類
3) 返回修改之後的類
"""
"""
為什麽要用metaclass類而不是函數?
由於__metaclass__可以接受任何可調用的對象,那為何還要使用類呢,因為很顯然使用類會更加復雜啊?這裏有好幾個原因:
1) 意圖會更加清晰。當你讀到UpperAttrMetaclass(type)時,你知道接下來要發生什麽。
2) 你可以使用OOP編程。元類可以從元類中繼承而來,改寫父類的方法。元類甚至還可以使用元類。
3) 你可以把代碼組織的更好。當你使用元類的時候肯定不會是像我上面舉的這種簡單場景,通常都是針對比較復雜的問題。將多個方法歸總到一個類中會很有幫助,也會使得代碼更容易閱讀。
4) 你可以使用__new__, __init__以及__call__這樣的特殊方法。它們能幫你處理不同的任務。就算通常你可以把所有的東西都在__new__裏處理掉,有些人還是覺得用__init__更舒服些。
5) 哇哦,這東西的名字是metaclass,肯定非善類,我要小心!
究竟為什麽要使用元類?
現在回到我們的大主題上來,究竟是為什麽你會去使用這樣一種容易出錯且晦澀的特性?好吧,一般來說,你根本就用不上它:
“元類就是深度的魔法,99%的用戶應該根本不必為此操心。如果你想搞清楚究竟是否需要用到元類,那麽你就不需要它。那些實際用到元類的人都非常清楚地知道他們需要做什麽,而且根本不需要解釋為什麽要用元類。” —— Python界的領袖 Tim Peters
"""
"""
知識點:
對象是類創建。創建對象時,類裏面的__init__方法會自動執行。 對象()會執行類的__call__方法。
類是type創建。創建類時,type的__init__方法會自動執行。 類()會執行執行type的__call__方法。執行完__call__方法後,call方法不僅會調用類的__new__方法,還會調用類的__init__方法。
# 第0步: 執行type的 __init__ 方法【類是type的對象】 class Foo: def __init__(self): pass def __call__(self, *args, **kwargs):pass # 第1步: 執行type的 __call__ 方法 # 1.1 調用 Foo類(是type的對象)的 __new__方法,用於創建對象。 # 1.2 調用 Foo類(是type的對象)的 __init__方法,用於對對象初始化。 obj = Foo() # 第2步:執行Foo def __call__ 方法 obj()
"""
元類相關(type & metaclass)