背景
平时我使用一个陌生的函数或者类的时候,都有一种习惯,那就是按ctrl键到这个类或函数的定义处,看看定义的详情,传入的参数之类的。直到有一天,我对Django的Model的objects定义很感兴趣,于是跟踪进去,发现,并没有找到objects的定义,这就奇怪了?
class Model(metaclass=ModelBase):
def __init__(self, *args, **kwargs):
# Alias some things as locals to avoid repeat global lookups
cls = self.__class__
opts = self._meta
_setattr = setattr
_DEFERRED = DEFERRED
只看到如上的定义。还有个问题就是,Django的Model写的时候,所有属性虽然是直接写在类里的,而不是写在init中,这意味定义时写的都是类属性?每次实例化时,每个对象只代表数据表中的一行,所有不应该定义为类属性的,但是Django的Model就是这么定义的,这个疑问困扰我好长时间,网上查也没查到,直到有一天看到metaclass时,才恍然大悟。
Metaclass
以前学习的时候学过元类和type,但是大概因为从来没有用过吧,忘的一干二净。
metaclass,我理解的就是可以动态的创建类,元类的实例化是类,类的实例化是对象。ORM就是一个典型的例子。
那为什么直接定义为类的属性呢?
因为Model实际是通过Metaclass生成的,它在动态生成ORM时,就从类属性提取所有类属性到一个mapping中,然后删除所有的类属性,这也就意味着动态生成的新类实际还是 对象的属性,而不是类属性。
提取到mapping中的属性方便了动态生成类,同时类的所有方法,比如动态生成的数据库插入函数 就可以拥有所有动态定义的字段了。