看一個手寫metaclass的實現:html
# -*- coding:utf-8 -*- # 2017/6/29 class Meta(type): def __new__(mcs, *args, **kwargs): print "Meta new" return type.__new__(mcs, "meta_class", (), {}) # 1 # return type('meta_class', (), {}) # 2 def __call__(cls, *args, **kwargs): return super(Meta, cls).__call__() # raise RuntimeError("initialize not allowed") def base_class_with_meta(cls, *base): class metaclass(Meta): def __new__(mcs, *args, **kwargs): return Meta(mcs, base, kwargs) return type.__new__(metaclass, "temp_meta_class", base, {}) class A(base_class_with_meta(Meta)): def __new__(cls, *args, **kwargs): return super(A, cls).__new__(args, kwargs) def __init__(self, *args, **kwargs): super(A, self).__init__(args, kwargs) a = A() b = A()
輸出python
D:\Python27\python.exe E:/workspace/lab_for_py/python-example-code/metaclass/test_metacalss_research.py Meta new Process finished with exit code 0
看代碼註釋1和2局有什麼區別函數
分析:spa
type(name, base, dicts)會生成一個新類,類的__name__ 爲name, 基類爲base,命名空間爲__dict__code
不會調用類定義的init方法,此句返回是一個徹底的新類,和Meta沒有任何關係htm
type.__new__(cls, name, base, dicts)會返回一個cls的instance,會調用init方法,此類爲Meta的實例對象
附上文檔:utf-8
https://docs.python.org/3/reference/datamodel.html?highlight=__new__#object.__new__文檔
參考連接:get
https://stackoverflow.com/questions/2608708/what-is-the-difference-between-type-and-type-new-in-python
對元類的理解:
在定義metaclass的時候__new__函數能夠控制類對象生成的過程,__init__函數能夠控制類對象的初始化,__new__和__init__ 均可以控制類內參數(並不能控制類實例的參數),__call__函數能夠控制類實例化變量的過程,好比實現單例。
搞這些東西的人,大家聽好了: