上一篇文章: Python==與is對比
下一篇文章: Python是動態語言:動態編輯屬性、動態編輯方法本篇內容只供瞭解,實際上99%的python程序員都用不到元類喲,不過你要想成爲那1%,請隨意享用,別客氣😆python
元類做用:攔截類的建立、修改類、返回修改以後的類程序員
萬物皆對象,類建立了實例對象,那既然萬物皆對象,類也是對象,那什麼建立了類呢,啦啦啦,固然就是本篇的主人翁:元類。編程
既然類也是一個對象,那就應該具備對象共有的特性:能夠將其賦給變量segmentfault
能夠拷貝函數
能夠增長屬性指針
能夠做爲函數參數進行傳遞code
實例:對象
class A: def hello_fun(self): print("Hello World") def test(a): print("類做爲函數參數傳遞:",a) #類也是對象,因此能夠打印 print(A) #由於類也是對象,因此能夠做爲函數參數進行傳遞 test(A) #hasattr用來判斷指定類中是有有對應屬性 print(hasattr(A,"mark"))#哼,我就是一個屬性,來打我呀 #添加屬性而且賦值 A.mark="帥"#mark是屬性名稱,帥是值 print(hasattr(A,"mark")) print("mark屬性值:",A.mark) #由於類是一個對象,因此能夠拷貝 B=A#拷貝 print(B)
運行結果:繼承
<class '__main__.A'> 類做爲函數參數傳遞: <class '__main__.A'> False True mark屬性值: 帥 <class '__main__.A'>
既然類也是對象,固然能夠動態建立,好比在函數內部建立。
實例:內存
def test(): class A: def hello_fun(self): print("Hello World") print("函數內部建立的類:",A) test()
運行結果:
函數內部建立的類: <class '__main__.test.<locals>.A'>
type函數除了能夠檢查類型外,另外一個高大上的用途就是動態建立類。語法:type(類名,由父類名稱組成的元組(能夠爲空),包含屬性的字典(名稱和值))
實例:
#定義一個沒有方法,沒有屬性的類:A A=type("A",(),{}) #打印A print(A) #打印A的實例 print(A()) print("*"*30) #定義一個帶兩個屬性的類:B B=type("B",(),{"name":"mark","age":18}) print(B.name) print(B.age) print("*"*30) #定義一個帶普通方法的類:C def test_for_c(self): print(self.name) C=type("C",(),{"name":"mark","age":18,"test_for_c":test_for_c}) c=C() c.test_for_c() print("*"*30) #添加靜態方法 @staticmethod def static_method_test(): print("static method test") D=type("D",(),{"name":"mark","age":18,"static_method_test":static_method_test}) D.static_method_test() print("*"*30) #添加類方法 @classmethod def class_method_test(cls): print(cls.name) E=type("E",(),{"name":"mark","age":18,"class_method_test":class_method_test}) e=E() e.class_method_test() E.class_method_test()
結果:
<class '__main__.A'> <__main__.A object at 0x10b7ac0f0> ****************************** mark 18 ****************************** mark ****************************** static method test ****************************** mark mark
實例:
class A(object,metaclass=xxxx): pass
滴答滴答,想象一下,解析指針如今運行到這個類的上面,此處類還沒加載到內存中,而後開始解析A,首先去A的定義中找,有沒有指定__metaclass__屬性,若是指定了,就利用這個指定的屬性來建立類,沒有指定就會用type開生成類。具體步驟以下:
如今自定義一個元類,保證全部的屬性名都大寫
實例:
def upper_attr(class_name,class_parent,class_attr): #遍歷屬性字典,把不是__開頭的屬性名稱都編程大寫 newAttr={} for name,value in class_attr.items(): if not name.startswith("__"): newAttr[name.upper()]=value #調用type來建立類 return type(class_name,class_parent,newAttr) class A(object,metaclass=upper_attr): mark="帥哥" print(hasattr(A,"mark")) print(hasattr(A,"MARK")) print(A.MARK)
結果:
False True 帥哥
如今自定義一個元類,保證全部的屬性名都大寫
實例:
class UpperAttrMetaClass(type): #__new__是在__init__以前被調用的特殊方法,用來建立對象並返回, #而__init__只是將傳遞的參數賦給對象 def __new__(cls,class_name,class_parent,class_attr): # 遍歷屬性字典,把不是__開頭的屬性名稱都編程大寫 newAttr = {} for name, value in class_attr.items(): if not name.startswith("__"): newAttr[name.upper()] = value # 方法1:調用type來建立類 #return type(class_name, class_parent, newAttr) #方法2:複用type.__new__方法 #return type.__new__(cls,class_name,class_parent,newAttr) #方法3:使用super方法 return super(UpperAttrMetaClass,cls).__new__(cls,class_name,class_parent,newAttr) class A(object,metaclass=UpperAttrMetaClass): mark="帥哥" print(hasattr(A,"mark")) print(hasattr(A,"MARK")) print(A.MARK)
結果:
False True 帥哥