python中base属性_python 中的metaclass和baseclasses

提前说明:

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在python层面对应的是 classname.__metaclass__这个对象,在C 源码层面就是 PyObject.ob_type这个对象了。

metaclass关乎 class object的创建

metaclass的确定次序:

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

2.baseclasses[0]中是否有定义__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__==

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值