看一个手写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__函数能够控制类实例化变量的过程,好比实现单例。
搞这些东西的人,大家听好了: