元类(MetaClasses)
元类提供了一个改变Python类行为的有效方式。
元类的定义是“一个类的类”。任何实例是它自己的类都是元类。
class demo(object):
pass
obj = demo()
print "Class of obj is {0}".format(obj.__class__)
print "Class of obj is {0}".format(demo.__class__)
# Class of obj is <class '__main__.demo'>
# Class of obj is <type 'type'>
在上例中,我们定义了一个类demo,并且生成了一个该类的对象obj。首先,可以看到obj的__class__是demo。有意思的来了,那么demo的class又是什么呢?可以看到demo的__class__是type。
所以说type是python类的类,换句话说,上例中的obj是一个demo的对象,而demo本身又是type的一个对象。
所以说type就是一个元类,而且是python中最常见的元类,因为它使python中所有类的默认元类。
因为元类是类的类,所以它被用来创建类(正如类是被用来创建对象的一样)。但是,难道我们不是通过一个标准的类定义来创建类的么?的确是这样,但是python内部的运作机制如下:
-
- 当看见一个类定义,python会收集所有属性到一个字典中。
- 当类定义结束,python将决定类的元类,我们就称它为Meta吧。
- 最后,python执行Meta(name, bases, dct),其中:
a. Meta是元类,所以这个调用是实例化它。
b. name是新建类的类名。
c. bases是新建类的基类元组
d. dct将属性名映射到对象,列出所有的类属性。
那么如何确定一个类(A)的元类呢?简单来说,如果一个类(A)自身或其基类(Base_A)之一有__metaclass__属性存在,则这个类(A/Base_A)就是类(A)的元类。否则type就将是类(A)的元类。
metaclass 原理
metaclass的原理其实是这样的:当定义好类之后,创建类的时候其实是调用了type的__new__方法为这个类分配内存空间,创建
好了之后再调用type的__init__方法初始化(做一些赋值等)。所以metaclass的所有magic其实就在于这个__new__方法里面了。
说说这个方法:__new__(cls, name, bases, attrs)
cls: 将要创建的类,类似与self,但是self指向的是instance,而这里cls指向的是class
name: 类的名字,也就是我们通常用类名.__name__获取的。
bases: 基类
attrs: 属性的dict。dict的内容可以是变量(类属性),也可以是函数(类方法)。
所以在创建类的过程,我们可以在这个函数里面修改name,bases,attrs的值来自由的达到我们的功能。这里常用的配合方法是
getattr和setattr(just an advice)