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