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

我們最常用到的元類就是奇妙的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í).
最后,都看到這了,贊賞一下唄!(^ ~ ^||).