在Python中,什么是元类?我们将它们用于什么?
元类是类的类。类定义类的实例(即对象)的行为,而元类定义类的行为。类是元类的实例。
尽管在Python中您可以对元类使用任意可调用对象(例如Jerub演示),但是更好的方法是使其成为实际的类。type是Python中常见的元类。type它本身是一个类,并且是它自己的类型。您将无法type纯粹在Python中重新创建类似的内容,但是Python有点作弊。要在Python中创建自己的元类,您实际上只想将其子类化type。
元类最常用作类工厂。当通过调用类创建对象时,Python通过调用元类来创建一个新类(当执行“ class”语句时)。因此,将元类与普通方法__init__和__new__方法结合使用,可以使您在创建类时做“额外的事情”,例如使用某些注册表注册新类或将其完全替换为其他类。
__init__
__new__
当class执行语句时,Python首先将class语句的主体作为普通代码块执行。生成的名称空间(字典)保留了将来类的属性。通过查看要成为类的基类(继承了元类),要成为类的__metaclass__属性(如果有)或__metaclass__全局变量来确定元类。然后使用该类的名称,基数和属性调用该元类以实例化它。
__metaclass__
但是,元类实际上定义了一个类的类型,而不仅仅是它的工厂,因此您可以使用它们做更多的事情。例如,您可以在元类上定义常规方法。这些元类方法就像类方法,因为它们可以在没有实例的情况下在类上调用,但是它们也不像类方法,因为它们不能在类的实例上被调用。type.subclasses()是type元类上方法的示例。您还可以定义正常的“魔力”的方法,如__add__,__iter__和__getattr__,执行或如何变化的类的行为。
__add__
__iter__
__getattr__
这是点滴的汇总示例:
def make_hook(f): """Decorator to turn 'foo' method into '__foo__'""" f.is_hook = 1 return f class 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_hook', 0): 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." % self class MyObject: __metaclass__ = MyType class 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 class Example.unregister() inst = Example(10) # Will fail with an AttributeError #inst.unregister() print inst + inst class Sibling(MyObject): pass ExampleSibling = 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 ExampleSibling print ExampleSibling.__mro__