|
在 Python 中,metaclasses我们用它们做什么?+ h9 E- q; B7 N* C& _
0 H2 P7 u; N* \0 H1 d2 ^8 K+ O 解决方案:
M9 W9 `7 s) P# |" @4 N metaclass是类。类定义类的实例(即对象)行为模式,而元类定义类的行为模式。metaclass的实例。8 G. B0 Z. m4 c' A, l6 j
虽然在 Python 你可以做到metaclass使用任何可调对象,但更好的方法是使其成为实际类本身。type是 Python 常见的元类。type它本身就是一个类它自己的类型。type完全用 Python重新创建类似的东西,但 Python 会作弊Python 创建自己的元类,你其实只想type.% h" c4 F$ l) Z
metaclass最常用作类工厂。当你通过调用类创建对象时,Python 将通过调用元类创建一个新当它执行时class语句时)。因此,结合常规__init__和__new__方法:元类允许你在创建类别时做额外的事情,比如用一些注册表注册新类别,或者用其他内容完全替换。
/ }/ L3 J$ m' v' \% e9 N当class被执行的句子,Python首先执行的主体class声明是代码的正常块。生成的命名空间( dict)保存类属性。metaclass是通过查看类的基类(metaclass是继承、类别__metaclass__属性(如有)或__metaclass__确定全局变量。然后调用类的名称、基类和属性metaclass以实例化为例。
! {' }8 e; O2 B8 ]# |9 K然而,metaclass实际上定义了一个类类型,而不仅仅是它的工厂,所以你可以用它们做更多的事情。例如,你可以metaclass定义普通方法。metaclass方法类似于类方法,因为它们可以在没有实例的类中调用,但它们不像类方法,因为它们不能在类实例中调用。type.__subclasses__()是type元类方法的一个例子。您还可以定义普通的魔法方法,例如__add__、__iter__和__getattr__,实现或改变类别的行为。
$ g8 o& j' z& r7 k( G这是一个总结的例子:5 m% n$ A: V4 _7 a, [8 r) a
def make_hook(f): """Decorator to turn 'foo' method into '__foo__'""" f.is_hook = 1 return fclass MyType(type): def __new__(mcls,name,bases,attrs): if name.startswith('None): return None # Go over attributes and see if they should be renamed. newattrs = for attrname,attrvalue in attrs.iteritems()if getattr(attrvalue,'is_hook0): newattrs['__%s__' % attrname] = attrvalue else: newattrs[attrname] = attrvalue return super(MyType,mcls).__new__(mcls,name,bases,newattrs) def __init__(self,name,bases,attrs): super(MyType,self).__init__(name,bases,attrs) # classregistry.register(self,self.interfaces) print "Would register class %s now." % self def __add__(self,other): class AutoClass(self,other): pass return AutoClass # Alternatively,to autogenerate the classname as well as the class: # return type(self.__name__ other.__name__,(self,other), def unregister(self): # classregistry.unregister(self) print "Would unregister class %s now." % selfclass MyObject: __metaclass__ = MyTypeclass NoneSample(MyObject): pass# Will print "NoneType None"print type(NoneSample),repr(NoneSample)class Example(MyObject): def __init__(self,value): self.value = value @make_hook def add(self,other): return self.__class__(self.value other.value)# Will unregister the classExample.unregister()inst = Example(10)# Will fail with an AttributeError#inst.unregister()print inst instclass Sibling(MyObject): passExampleSibling = Example Sibling# ExampleSibling is now a subclass of both Example and Sibling (with no# content of its own) although it will believe it's called 'AutoClass'print ExampleSiblingprint ExampleSibling.__mro__" t5 l `3 F. Z9 @( W8 o Y
|
|