6.10 元类
所谓元类,就是一个用来当作创建其他类的模板(template)的类。一般来讲,用户使用类来创建类实例变量。使用元类的目的是以某些类为基准来创建metaclass类,然后将元类当作要创建的类的基类。
使用元类让用户有机会可以存取与改变Python的内部类。利用元类创建的元实例可以让操作对象属性的工作更容易。
下列程序代码定义一个简单的元类与其支持的类:
1: >>>import types 2: >>>class METACLASS: 3: def __init__(self, name, bases, namespace): 4: self.__name__ = name 5: self.__bases__ = bases 6: self.__namespace__ = namespace 7: def __call__(self): 8: return METAINSTANCE(self) 9: 10: >>> class METAINSTANCE: 11: def __init__(self, metaclass): 12: self.__metaclass__ = metaclass 13: def __getattr__(self, name): 14: try: 15: value = self.__metaclass__.__namespace__[name] 16: except KeyError: 17: raise AttributeError.name 18: if type(value) is not types.FunctionType: 19: return value 20: return METHODWRAPPER(value, self) 21: 22: >>> class METHODWRAPPER: 23: def __init__(self, function, metainstance): 24: self.function = function 25: self.instance = metainstance 26: self.__name__ = self.function.__name__ 27: def __call__(self, *args): 28: return apply(self.function, (self.instance, ) + args) 29:
上述代码的含义分析如下。
(1)第2行:定义一个元类,类名称为METACLASS。
(2)第3~6行:创建一个新的元类,此元类的构造方法需要3个参数。name参数是元实例的名称,bases参数是一个基类的元组,namespace参数是元实例命名空间的字典。
(3)第7~8行:当调用METACLASS时,运行METAINSTANCE.__init__()来返回一个元实例。
(4)第10行:定义一个元实例,类名称为METAINSTANCE。
(5)第13行:存取此用户定义实例变量的属性时,检查它是否属于用户类命名空间(第14~17行)。如果此属性是一个数值,则返回此数值;若此属性是一个函数,返回一个METHODWRAPPER类的实例。
(6)第22行:定义一个类,名称为METHODWRAPPER,用来处理存取用户类的方法属性。
下列程序代码创建一个元类的实例:
>>> BASECLASS = METACLASS("BASECLASS", (), {})
下列程序代码以BASECLASS当作基类,来创建一个用户类:
>>>class myClass(BASECLASS): def push(self, name): self.name = [name] def pop(self): if len(self.name) > 0: item = self.name[-1] print (item)
下列案例使用用户类myClass来新增与删除name属性:
1: >>>x = myClass() 2: >>>x.push("Andre") 3: >>>x.name 4: ['Andre'] 5: >>> x.pop() 6: Andre 7: >>> x.name 8: []
上述代码的含义分析如下
(1)第1行:创建一个用户定义类myClass的实例x。当创建x时,会运行METACLASS.__call__()函数。而METACLASS.__call__()函数又会调用METAINSTANCE.__getattr__()。
(2)第2行:新增一个name属性"Andre"。
(3)第3~4行:显示实例x的name属性。
(4)第5行:删除name属性列表的最后一个元素Andre。
(5)第7~8行:显示实例x的name属性。