提前说明:

class object  指VM中的class 对象,因为python一切对象,class在VM也是一个对象,需要区分class对象和 class实例对象。

class instance 指 某个class的 instance ,这个instance 的 ob_type指向某个 class object

  

python中 类对象有两种相关的class需要我们特别关注:

1.metaclass:

  metaclass关乎class object(不是 class instance)的创建。

  在python中一般class的metaclass是type这个typeobject。

  用type创建class object 例子:

  

#class instance 初始化方法
def __myinit__(self,arg):
print("__myinit__")
self.arg=arg def classmethod1(self):
print(self.arg) #class object's dict
attrs = {'__init__': __myinit__, 'classmethod1': classmethod1}
#基类
bases=(object,) ClassObject=type("ClassObject",bases,attrs) classInstance=ClassObject("abcde")
classInstance.classmethod1()

通过meataclass 来创建 classobject实例:

class MyMetaclass(type):
def __new__(clz,name,bases,attrs):
print("create new class ",name)
return type.__new__(clz, name, bases, attrs) class UseMetaclass(object):
__metaclass__=MyMetaclass
def __init__(self, arg):
super(UseMetaclass, self).__init__()
self.arg = arg print type(UseMetaclass)
#<class 'A.MyMetaclass'>

  

  

  这个class在python层面对应的是 classname.__metaclass__这个对象,在C 源码层面就是 PyObject.ob_type这个对象了。

  metaclass关乎 class object的创建

metaclass的确定次序:

1.定义类时是否有__metaclass__这个field

2.baseclasses[]中是否有定义__metaclass__这个field,这个查找步骤会一直向父类baseclasses[0]递归

3.global名字空间中是否有__metaclass__这个field

4.实在都没有了(正常状态),__metaclass__就用PyClass_Type

static PyObject *
build_class(PyObject *methods, PyObject *bases, PyObject *name)
{
PyObject *metaclass = NULL, *result, *base; //检查属性是否已经填了__metaclass__
if (PyDict_Check(methods))
metaclass = PyDict_GetItemString(methods, "__metaclass__"); if (metaclass != NULL){
/*
print_obj(metaclass); printf("\n");
*/
Py_INCREF(metaclass); }
else if (PyTuple_Check(bases) && PyTuple_GET_SIZE(bases) > 0) {
//从第一个基类里找__metaclass__,就是第一个基类的ob_type了,base 一般会是object 就是 那个PyBaseObject_Type,所以base.ob_type 就是PyType_Type ,这个class 对象就是 metaclass了
// object.__class__==<type 'type'>
base = PyTuple_GET_ITEM(bases, 0);
metaclass = PyObject_GetAttrString(base, "__class__");
if (metaclass == NULL) {
PyErr_Clear();
metaclass = (PyObject *)base->ob_type;
Py_INCREF(metaclass);
}
//print_obj(metaclass);
}
else {
// 这个else 处理 classic 的类定义方式
PyObject *g = PyEval_GetGlobals();
if (g != NULL && PyDict_Check(g))
metaclass = PyDict_GetItemString(g, "__metaclass__");
if (metaclass == NULL)
metaclass = (PyObject *) &PyClass_Type;
Py_INCREF(metaclass);
}
//以上代码都为弄到一个__metaclass__ /*
创建一个类型对象, 调用metaclass ,会调用到 metaclass的 tp_call ,然后 还会调用到 type_new 创建一个新的类型对象,metaclass 是一个callable的对象
*/
result = PyObject_CallFunctionObjArgs(metaclass, name, bases, methods,
NULL);
Py_DECREF(metaclass);
if (result == NULL && PyErr_ExceptionMatches(PyExc_TypeError)) {
/* A type error here likely means that the user passed
in a base that was not a class (such the random module
instead of the random.random type). Help them out with
by augmenting the error message with more information.*/ PyObject *ptype, *pvalue, *ptraceback; PyErr_Fetch(&ptype, &pvalue, &ptraceback);
if (PyString_Check(pvalue)) {
PyObject *newmsg;
newmsg = PyString_FromFormat(
"Error when calling the metaclass bases\n"
" %s",
PyString_AS_STRING(pvalue));
if (newmsg != NULL) {
Py_DECREF(pvalue);
pvalue = newmsg;
}
}
PyErr_Restore(ptype, pvalue, ptraceback);
}
return result;
}

  

2.baseclasses:

  这个class就是所谓的基类了。

用class.mro()获取所有基类,这个返回的集合中从 序号1开始才是真正所谓的基类。

最新文章

  1. try catch 与 throw拾遗
  2. windows 下 redis for php 配置
  3. 【转发】Linux下如何查看当前支持的文件系统及各分区的文件系统类型
  4. 关于Flash Builder
  5. 安装VMware vCenter过程设置数据库方法
  6. css3学习系列之选择器(一)
  7. 在64位系统下,指向int型的指针占的内存空间多大?
  8. leafLet入门教程兼leafLet API中文文档参考
  9. linux 命令 创建 Django 项目 使用路由返回首页界面
  10. JS canvas 画板 撤销
  11. 791. Custom Sort String字符串保持字母一样,位置可以变
  12. Omi-router实战 Sorrow.X的web简历
  13. 【BZOJ】4292: [PA2015]R&#243;wnanie
  14. 记一次坑爹的golang 二维map判断问题
  15. Python中表达式和语句及for、while循环练习
  16. Autofac容器使用属性进行WebApi自动注入
  17. LandMVC HttpHandler web.config配置
  18. 前端自动化之gulp
  19. 关闭浏览器session就被干掉的假象的问题
  20. VIM-不常用或不知道的技巧

热门文章

  1. django--models操作
  2. 解决警告“ld: warning: directory not found for option
  3. django url.py使用
  4. Oracle的DML语言必备基础知识
  5. find命令的拾遗
  6. http 登录Digest认证相关知识
  7. aischool 倒计时VIEW封装
  8. 利用lambda和Collection.forEach
  9. [liusy.api-SMJ]-MAVEN archetype 创建项目
  10. MATLAB的GUI