簡單定義「元編程是一種編寫計算機程序的技術,這些程序能夠將本身看作數據,所以你能夠在運行時對它進行內審、生成和/或修改」,本博參考<<Python高級編程>>將對元編程內容進行詳細描述,如有不正確之處但願你們指出。
Python元編程有兩種方法,一是採用相似「裝飾器」的工具對基本元素(例如函數、類、類型)內審和對其進行實時建立和修改,二是運用類型"元類"的方式對類實例的建立過程進行修改,甚至於容許從新設計Python面對對象編程範式的實現。html
關於裝飾器的內容能夠閱讀上篇博客<<Python裝飾器>>,連接:http://www.cnblogs.com/xiaobingqianrui/p/8435074.html編程
對wraps裝飾器的使用進行補充說明,在類裝飾器中使用閉包會致使生成的對象再也不是被裝飾的類的實例,二是在裝飾器函數建立的子類的實例,這會影響__name__和__doc__等屬性,在上篇咱們使用@wraps裝飾器對函數裝飾器進行操做讓問題獲得解決,但在類裝飾器中這一方法無效。
元類是Python的一個重要特性,是定義其餘類的類,理解其工做方式,最重要的是要知道定義了對象實例的類也是對象,那麼它必定有與其相關聯的類,全部的類定義的基類都是內置的type類。閉包
#coding=utf-8 class MyClass: pass if __name__ == "__main__": myclass = MyClass() print ("type of myclass:", type(myclass)) print ("type of MyClass:", type(MyClass))
>>> type of myclass: <class '__main__.MyClass'>
>>> type of MyClass: <class 'type'>函數
type()類做爲class語句的動態等效,給定類名,基類名和屬性映射會建立一個新類 工具
#coding=utf-8 def func1(self): print (1) def func2(*argv): print (argv) if __name__ == "__main__": MyClass = type("MyClass",(object, ), {"func1":func1, "func2":func2}) a = MyClass() print (type(a)) a.func1() a.func2(2)
>>> <class '__main__.MyClass'>
>>> 1
>>> (<__main__.MyClass object at 0x01A02270>,2)ui
#coding=utf-8 '''元類模板 ''' class MyClass(type): #建立一個空的命名空間,返回一個空的dict @classmethod def __prepare__(mcs, name, bases, **kwargs): print ("MyClass __prepare__") return super().__prepare__(name, bases, **kwargs) def __new__(mcs, name, bases, namespace): print ("MyClass __new__") return super().__new__(mcs, name, bases, namespace) def __init__(cls, name, bases, namespace, **kdargv): print ("MyClass __init__") super().__init__(name, bases, namespace) def __call__(cls, *argv, **kdargv): print ("MyClass __call__") return super().__call__(*argv, **kdargv) class _MyClass(metaclass=MyClass): def __new__(cls): print ("_MyClass __new__") return super().__new__(cls) def __init__(self): print("__MyClass __init__") super().__init__() if __name__ == "__main__": a = _MyClass()
>>> MyClass __prepare__
>>> MyClass __new__
>>> MyClass __init__
>>> MyClass __call__
>>> _MyClass __new__
>>> __MyClass __init_spa
用class語句建立的每一個類都隱式的使用type做爲元類,能夠用metaclass=「指定元類」的方式改變這一默認行爲。
元類是一種很是強大的特性,但老是會是代碼更加複雜,將其用於任意類型的類時,這可能會下降代碼的魯棒性,咱們必須靈活的使用元類。設計
#coding=utf-8 class OrderedMeta(type): @classmethod def __prepare__(mcs, name, bases, **kdargv): return super().__prepare__(mcs, name, bases, **kdargv) def __new__(mcs, name, bases, namespace): namespace["orderofattr"] = list(namespace.keys()) return super().__new__(mcs, name, bases, namespace) class test(metaclass = OrderedMeta): first = 8 secord = 2 if __name__ == "__main__": print (test.orderofattr) print (test.__dict__.keys())
>>> ['__module__', '__qualname__', 'first', 'secord']
>>> dict_keys(['__module__', 'first', 'secord', 'orderofattr', '__dict__', '__weakre
>>> f__', '__doc__'])code