您的位置:首页 > 编程语言 > Python开发

python_metaclass浅析

2015-07-15 18:05 615 查看
Python对象机制和metaclass

1

Python一切皆对象

Python的类是对象:这个对象(类)自身拥有创建对象(类实例)的能力,而这就是它是一个类的原因

创建Python类对象的类是什么?元类。这就是“what is behind the hood”

那Python一切都是对象了,很自然的,元类也应该是个对象;那么创建元类对象的类是什么?

首先,元类不是指单个的类,和普通的类一样,元类也有它的继承层次,而最底层的元类叫做type类,那么这个最底层的元类(对象)是由什么创建的呢?它的元类是什么呢?是它自己。在纯Python环境中这可不是你能够做到的,这是通过在实现层面耍一些小手段做到的

元类和我们平常的应用有什么关系呢?当我们创建类的时候,用class,前面说过,类type的一个构造函数中,第一个参数是类名,第二个参数是继承的基类,第三个参数是类对象的变量,class的使用实际上是将你写在class缩进区域里面的一堆东西统统交给元类去处理(这里是type),然后再由元类生成类对象。你拿到这堆东西之后可以对它做修改,当然,你可能会问,为什么不直接在类里面改好,而要放到元类去改呢?首先,有一个重用的问题;另外,使用元类可以把对类的修改行为隐藏起来,你编的时候可以编的很好看,复杂的转换和动态修改你可以放到元类完成。所以,元类的一个主要的用途就是创建API,例如Django中的ORM使用了元类,而它使用的元类就是随着Django分发出来的;这样,我们就可以暴露出简单的API,而在背后完成真正的工作。

在Django的ORM机制中,class Person(models.Model),这个语句继承了Django distribution中的models.Model,而那里就是他们编写的元类所在。

class关键字将自己的一些参数交给元类让它创建类对象,寻找的过程是这样的:现在class里面找__metaclass__,如果找不到,就到父类去找,一直沿着继承关系找下去,继承链跑完了就到模块层次中去寻找metaclass,是的,你可以在模块里面定义metaclass,那么在这个模块里面定义的所有的类都会交给这个元类处理(就近原则?),如果最后都找不到,就使用python内置的元类type

2

关于Python一切皆对象:

在Python源代码中的objects/文件夹里,就是python对象的底层实现

boolobject.c

bufferobject.c

bytearrayobject.c

cellobject.c

classobject.c

cobject.c

codeobject.c

complexobject.c

descrobject.c

dictobject.c

enumobject.c

fileobject.c

floatobject.c

frameobject.c

funcobject.c

genobject.c

intobject.c

iterobject.c

listobject.c

longobject.c

memoryobject.c

methodobject.c

moduleobject.c

rangeobject.c

setobject.c

sliceobjet.c

stringobject.c

tupleobject.c

typeobject.c

unicodeobject.c

weakrefobject.c

给出一个PyInt_Type的实现:

PyTypeObject PyInt_Type = {
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
    "int",
    sizeof(PyIntObject),
    0,
    (destructor)int_dealloc,                    /* tp_dealloc */
    (printfunc)int_print,                       /* tp_print */
    0,                                          /* tp_getattr */
    0,                                          /* tp_setattr */
    (cmpfunc)int_compare,                       /* tp_compare */
    (reprfunc)int_to_decimal_string,            /* tp_repr */
    &int_as_number,                             /* tp_as_number */
    0,                                          /* tp_as_sequence */
    0,                                          /* tp_as_mapping */
    (hashfunc)int_hash,                         /* tp_hash */
    0,                                          /* tp_call */
    (reprfunc)int_to_decimal_string,            /* tp_str */
    PyObject_GenericGetAttr,                    /* tp_getattro */
    0,                                          /* tp_setattro */
    0,                                          /* tp_as_buffer */
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
        Py_TPFLAGS_BASETYPE | Py_TPFLAGS_INT_SUBCLASS,          /* tp_flags */
    int_doc,                                    /* tp_doc */
    0,                                          /* tp_traverse */
    0,                                          /* tp_clear */
    0,                                          /* tp_richcompare */
    0,                                          /* tp_weaklistoffset */
    0,                                          /* tp_iter */
    0,                                          /* tp_iternext */
    int_methods,                                /* tp_methods */
    0,                                          /* tp_members */
    int_getset,                                 /* tp_getset */
    0,                                          /* tp_base */
    0,                                          /* tp_dict */
    0,                                          /* tp_descr_get */
    0,                                          /* tp_descr_set */
    0,                                          /* tp_dictoffset */
    0,                                          /* tp_init */
    0,                                          /* tp_alloc */
    int_new,                                    /* tp_new */
    (freefunc)int_free,                         /* tp_free */
};


一个对象怎么判断它的元类,用type类。

例如type(1)–>< type ‘int’>实际上就是沿着PyObject或者PyVarObject的ob_type指针去寻找的



type()获得的结果和这些Py____Type获得的结果是对应的

note:

这篇只是从github搬运过来一下,原文地址https://github.com/lao605/python_metaclass
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: