提前说明:

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开始才是真正所谓的基类。

python 中的metaclass和baseclasses的更多相关文章

  1. python中的metaclass

    首先看下面的代码: # coding: utf-8 class Test(object): pass print Test.__class__ # type print Test.__base__ # ...

  2. python 中的 metaclass

    最遇到一个问题. class Meta(type): pass class M1(Meta): pass class M2(metaclass=M1): pass class Test(M2,meta ...

  3. Python中的__init__和__new__

    一.__init__ 方法是什么? 使用Python写过面向对象的代码的同学,可能对 __init__ 方法已经非常熟悉了,__init__ 方法通常用在初始化一个类实例的时候.例如: # -*- c ...

  4. python中的__init__和__new__的区别

    一.__init__ 方法是什么?(init前后的线是双下划线) 使用Python写过面向对象的代码的同学,可能对 __init__ 方法已经非常熟悉了,__init__ 方法通常用在初始化一个类实例 ...

  5. Python中__new__的作用

    __new__ 的作用 依照Python官方文档的说法,__new__方法主要是当你继承一些不可变的class时(比如int, str, tuple), 提供给你一个自定义这些类的实例化过程的途径.还 ...

  6. Python中__init__和__new__的区别详解

    __init__ 方法是什么? 使用Python写过面向对象的代码的同学,可能对 __init__ 方法已经非常熟悉了,__init__ 方法通常用在初始化一个类实例的时候.例如: # -*- cod ...

  7. 详解Python中的__init__和__new__(静态方法)

    一.__init__ 方法是什么? 使用Python写过面向对象的代码的同学,可能对 __init__ 方法已经非常熟悉了,__init__ 方法通常用在初始化一个类实例的时候.例如: #-*- co ...

  8. Python中的 _init__和 _new__的区别

    使用python 的面向对象写过程序之后,相信童鞋对 __init__ 方法已经非常的熟悉了.这个方法通常是 在初始化一个实例的时候使用的. 例如: class MysqlConnector(obje ...

  9. 详解Python中的__init__和__new__

    转载:https://my.oschina.net/liuyuantao/blog/747164 1.__init__ 方法是什么? 使用Python写过面向对象的代码的同学,可能对 __init__ ...

随机推荐

  1. SQL学习整理_2

    字符串处理,字符串函数不会改变存储在表中的数据内容,他们只是把函数结果当成查询结果返回. 1. SELECT right(name,2) FROM my_list   --从my_list列表中取出n ...

  2. 【原创】Android selector选择器无效或无法正常显示的一点研究

    想将LinearLayout作为一个按钮,加上一个动态背景,按下的时候,背景变色,这个理所当然应该使用selector背景选择器来做: <LinearLayout android:id=&quo ...

  3. Python模块应用 (linecache)

    linecache linecache是专门支持读取大文件,而且支持行式读取的函数库. linecache 预先把文件读入缓存起来,后面如果你访问该文件的话就不再从硬盘读取.对于大文件的读取效率还不错 ...

  4. option(recompile)

    Ref: http://www.cnblogs.com/CareySon/archive/2013/05/04/PlanCacheInSQLServerPart2.html https://msdn. ...

  5. linux查看某个进程内存占用情况以及/proc/pid/status解释

    以nginx 为例1.toptop -b -n 1 |grep nginx|awk '{print "VIRT:"$5,"RES:"$6,"cpu:& ...

  6. WebForm 页面传值

    一.使用Querystring Querystring是一种非常简单的传值方式,其缺点就是会把要传送的值显示在浏览器的地址栏中,并且在此方法中不能够传递对象.如果你想传递一个安全性不是那么太重要或者是 ...

  7. hibernate 多表查询

    Hibernate主要支持两种查询方式:HQL查询和Criteria查询.前者应用较为广发,后者也只是调用封装好的接口. 现在有一个问题,就是实现多表连接查询,且查询结果集不与任何一个实体类对应,怎么 ...

  8. Activity 横竖屏切换

    前言 在开发中常要处理横竖屏切换,怎么处理先看生命周期 申明 Activity 横竖屏切换时需要回调两个函数 ,所以在此将这个两个函数暂时看成是Activity 横竖屏切换的生命周期的一部分,这两个函 ...

  9. Java操作excel

    慕课网的好课程: http://www.imooc.com/learn/354

  10. Redis与Memcache的区别

    Redis与Memcache的区别 数据类型:  redis数据类型丰富,支持set liset等类型          memcache支持简单数据类型,需要客户端自己处理复杂对象 持久性: red ...