|
在 Python 中,metaclasses我们用它们做什么?
% ~( c. b: l5 J9 P2 C, d ) O4 o2 E; x/ n, M, ?' W+ |# j" q5 K
解决方案:
# G+ [" \# \5 L) O, e metaclass是类。类定义类的实例(即对象)行为模式,而元类定义类的行为模式。metaclass的实例。! C% M0 i5 q: S. V' q
虽然在 Python 你可以做到metaclass使用任何可调对象,但更好的方法是使其成为实际类本身。type是 Python 常见的元类。type它本身就是一个类它自己的类型。type完全用 Python重新创建类似的东西,但 Python 会作弊Python 创建自己的元类,你其实只想type.
, |, @" e! S5 Fmetaclass最常用作类工厂。当你通过调用类创建对象时,Python 将通过调用元类创建一个新当它执行时class语句时)。因此,结合常规__init__和__new__方法:元类允许你在创建类别时做额外的事情,比如用一些注册表注册新类别,或者用其他内容完全替换。
0 b0 r7 {% ^; e当class被执行的句子,Python首先执行的主体class声明是代码的正常块。生成的命名空间( dict)保存类属性。metaclass是通过查看类的基类(metaclass是继承、类别__metaclass__属性(如有)或__metaclass__确定全局变量。然后调用类的名称、基类和属性metaclass以实例化为例。
( H: N" G; N& g4 W1 N0 a# ^然而,metaclass实际上定义了一个类类型,而不仅仅是它的工厂,所以你可以用它们做更多的事情。例如,你可以metaclass定义普通方法。metaclass方法类似于类方法,因为它们可以在没有实例的类中调用,但它们不像类方法,因为它们不能在类实例中调用。type.__subclasses__()是type元类方法的一个例子。您还可以定义普通的魔法方法,例如__add__、__iter__和__getattr__,实现或改变类别的行为。$ D+ ]( h$ M/ b$ Z' s" j. k6 F
这是一个总结的例子:
3 V' b% s) x) w* Z1 ndef 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__
7 |2 Y2 d$ K4 O |
|