Python神技-元類

元類是Python中一種神奇的特性,可以實(shí)現(xiàn)像魔法一樣的效果,要理解元類,首先要先理解Python的類.Python中一切都是對象,包括類,他們的關(guān)系:


類的關(guān)系.png

我們最常用到的元類就是奇妙的type,一般情況下,type被用來檢測某個(gè)對象的類型,比如:

>>>type(1)
<class 'int'>
>>>type("a")
<class 'str'>
>>>type("true")
<class 'bool'>

那么類的類是什么?

class Class:
    pass
print(type(Class))       #是什么?
# <class 'type'>

是的,是type!所以我們也可以用type來創(chuàng)建類.雖然所有人都知道,用同一個(gè)函數(shù)僅僅傳入不同的參數(shù)就實(shí)現(xiàn)完全不同的功能,是非常愚蠢的做法.但Python這么做是為了向后兼容,所以似乎也沒什么可指責(zé)的.type的定義:

def type(name:str,base:tuple,namespace:dict)->type:pass
#name:類名
#bases:繼承的類
#namespace:類屬性,注意不是實(shí)例屬性

正常的類都是由type創(chuàng)建出來的,但我們也可以創(chuàng)建自己的元類,讓他繼承自type,并設(shè)定某個(gè)類使用它.而這個(gè)類的子類也就同樣是這個(gè)元類產(chǎn)生出的類.一個(gè)基本的元類如下:

class MetaClass(type):
    def __new__(cls,name,bases,namespace):
        #執(zhí)行操作...
        #其實(shí)下面那行也可以改成return type(name,bases,namespace),但這樣保持了代碼的一致性.
        return super().__new__(cls,name,bases,namespace)
    @classmethod
    def __prepare__(cls,name,bases,**kwargs):
        return super().__prepare__(name,bases,**kwargs)
    def __init__(self,name,bases,namespace,**kwargs):
        #執(zhí)行操作,注意這里雖然是self,但其實(shí)就是指我們的類,因?yàn)檫@個(gè)類的實(shí)例是類
        return super().__init__(name,bases,namespace,**kwargs)
    def __call__(self,*args,**kwargs):
        return super().__call__(*args,**kwargs)

有了元類,我們就要把它應(yīng)用到正常的類中,這里介紹Python3的語法,Python2因?yàn)橐呀?jīng)有些過時(shí)這里就不在說了.語法:

class Class(metaclass=MetaClass):
    pass

這樣我們就擁有了一個(gè)以我們自己的元類為元類創(chuàng)建出來的類了.元類可以為我們的類添加很多神奇的功能.比如說,如果不使用元類,很難想象Django的ORM,也就是Django的Model部分是如何實(shí)現(xiàn)的.當(dāng)然大家都會(huì)說,Django并沒有讓你在Class的括號(hào)里寫metaclass,很簡單,當(dāng)一個(gè)類使用了我們自己定義的元類后,它的子類也會(huì)使用它,比如說,我們接下來再定義一個(gè)ChildClass:

class ChildClass(Class):
    pass

運(yùn)行后會(huì)發(fā)現(xiàn),它使用的同樣是我們的元類,而不是默認(rèn)的type.

最后,再次提醒一遍,除非是為了做框架,或者為了學(xué)習(xí)Python中神妙的特性,否則不要在你的項(xiàng)目中使用元類.它會(huì)讓那些不了解你底層實(shí)現(xiàn)的人十分困惑.

(元類)是深?yuàn)W的知識(shí),99%的用戶都無須關(guān)注,如果你想知道是否需要使用元類,我告訴你,不需要(真正需要使用的人確信他們需要,無需解釋原因)
——Tim Peter(Timsort排序算法發(fā)明者)



以上是這篇文章的全部,錯(cuò)誤的地方懇請指正.
希望能和大家一起學(xué)習(xí).
最后,都看到這了,贊賞一下唄!(^ ~ ^||).

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容