Python之元类
类型对象负责创建对象实例,控制对象行为。那么类型对象又由谁来创建呢?
元类(metaclass)——类型的类型
New-Style Class的默认类型是type
>>> class Data(object): ... pass ... >>> >>> Data.__class__ <type 'type'> >>> >>> type.__class__ <type 'type'>
#最终的类型是type,包括type自己
关键字class会被编译成元类创建类型对象指令
>>> Data = type("Data",(object),{"x":1}) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: type() argument 2 must be tuple, not type >>> Data = type("Data",(object,),{"x":1})#class的实际行为 >>> >>> Data.x 1 >>> Data.__class__ <type 'type'> >>> >>> Data.__base__ <type 'object'>
class type(object) | type(object) -> the object's type | type(name, bases, dict) -> a new type
正因为class和def一样是指令,可以在任何地方创建类型对象。
>>> def test(): ... class Data(object):pass ... return Data ... >>> >>> Data = test() >>> >>> Data.__name__ 'Data' >>> >>> type(Data) <type 'type'> >>> >>> Data() <__main__.Data object at 0x7f822e1d2490>
元类、类型以及实例的创建顺序:
class = metaclass(....) #元类创建类型 instance = class(...) #类型创建实例 instance.__class__ is class #实例的类型 class.__class__ is metaclass #类型的类型
__metaclass__
除了使用默认元类type以外,还可以用__metaclass__属性指定自定义元类,以便对类型对象创建过程进行干预。
#!/usr/bin/env python26 #-*- coding:utf-8 -*- class InjectMeta(type): def __new__(cls,name,bases,attrs): t = type.__new__(cls,name,bases,attrs) def print_id(self):print hex(id(self)) t.print_id = print_id #为类型对象添加实例方法 t.s = "Hello,world!" #添加静态字段 return t class Data(object): __metaclass__ = InjectMeta #显示指定元类 print Data.__metaclass__ print Data.__class__ print Data.s print dir(Data) Data().print_id()
输出:
<class '__main__.InjectMeta'> <class '__main__.InjectMeta'> Hello,world! ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__metaclass__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'print_id', 's'] 0x7f3687df7250
自定义元类通常都从type继承,习惯以Meta结尾。和继承有点类似。
只需注意__new和__init__方法参数的区别:
http://www.cnblogs.com/gsblog/p/3368304.html
当解释器创建类型对象时,会按以下顺序查找__metaclass__属性:
class.__metaclass__->bases.__metaclass__->module.__metaclass__->type
magic
对象行为由类型决定。实例不过存储状态数据。控制类型对象的创建,也就意味着可以让对象的实际行为和代码存在极大的差异。这是魔法的力量。
静态类(static class):不允许创建实例。通常作为工具类(Utility)存在
[root@typhoeus79 20131014]# more static_class.py #!/usr/bin/env python26 #-*- coding:utf-8 -*- class StaticClassMeta(type): def __new__(cls,name,bases,attr): t = type.__new__(cls,name,bases,attr) def ctor(cls,*args,**kwargs): raise RuntimeError("Cannot be created a instance of the static class!") t.__new__ = staticmethod(ctor) return t class Data(object): __metaclass__ = StaticClassMeta Data() [root@typhoeus79 20131014]# ./static_class.py Traceback (most recent call last): File "./static_class.py", line 16, in <module> Data() File "./static_class.py", line 9, in ctor raise RuntimeError("Cannot be created a instance of the static class!") RuntimeError: Cannot be created a instance of the static class!
密封类(sealed class):禁止被继承
>>> class SealedClassMeta(type): ... _types = set() ... def __init__(cls,name,bases,attrs): ... if cls._types & set(bases): ... raise SyntaxError("Cannot inherit from a sealed class!") ... cls._types.add(cls) ... >>> >>> class A(object): ... __metaclass__ = SealedClassMeta ... >>> class B(A):pass ... Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 5, in __init__ SyntaxError: Cannot inherit from a sealed class!