标签:log 通过 就是 ash blog 学习 完成 支持 dea
对象是数据以及基于这些数据的操作的集合,在Python中,对象就是为C中的结构体在堆上申请的一块内存。
在Python中,一个对象一旦被创建,它在内存中的大小就是不变的了,那些需要容纳可变长度数据的对象只能在对象内维护一个指向一块可变大小的内存区域的指针。
[object.h]
typedef struct _object{
int ob_refcnt; /* 引用计数器 */
struct _typeobject *ob_type; /* _typeobject这个结构体用来指定一个对象类型的类型对象 */
} PyObject
在Python中,对象机制的核心非常简单,一个是引用计数,一个是类型信息
在PyObject中定义了每一个Python对象都必须有的内容,除了PyObject以外,还应该有一些额外的内存,放置其他信息。
typedef struct{
PyObject_HEAD
long ob_ival;
} PyIntObject
整数对象的特殊信息是一个C中的整形变量,无论这个整数对象的值有多大,都可以保存在这个整形变量中。
#define PyObject_VAR_HEAD PyObject_HEAD int ob_size; /* 容器中元素的数量 */
typedef struct{
PyObject_VAR_HEAD
} PyVarObject;
我们把整形对象这样不包含可变长度数据的对象称为“定长对象”,而字符串对象这样包含可变长度数据的对象称为“变长对象”,它们的区别在于定长对象的不同对象占用内存大小是一样的,而变长对象的不同对象占用内存可能不一样。
PyVarObject只是对PyObject的一个扩展而已,在Python内部,每一个对象都拥有相同的对象头部。
创建对象的时候,必须知道要申请多大的空间,所需空间大小是对象的一种元信息,这样的元信息与对象所属类型密切相关。我们考察一下类型对象_typeobject:
typedef struct _typeobject {
PyObject_VAR_HEAD
char *tp_name; /* tp_name 类型名 */
int tp_basicsize, tp_itemsize; /* 创建该类型对象时分配内存空间的大小 */
/* 与对象关联的操作信息 */
destructor tp_dealloc;
printfunc tp_print;
/* 更多操作信息 */
hashfunc tp_hash;
ternaryfunc tp_call;
...
} PyTypeObject;
一个PyTypeObject就是Python中面向对象理论中“类”这个概念的实现
Python创建对象的方法:
Python对外提供了C API让用户可以从C环境中与Python交互,Python的C API分为两类:
说明: 在Python完成运行环境的初始化后,符号‘int‘就对应着Python内部的PyInt_Type对象,object则对应着PyBaseObject_Type对象
当我们用int(10)创建整数对象10时,首先PyInt_Type中的tp_new会被调用,如果这个tp_new为NULL,那么会到tp_base指定的基类中去寻找tp_new操作
在PyTypeObject中定义了大量的函数指针,这些函数都最终会指向某个函数,或者指向NULL,这些函数指针可以视为类型对象中所定义的操作,而这些操作直接决定着一个对象在运行时所表现出的行为。
比如PyTypeObject中的tp_hash是一个函数指针(hashfunc)类型的变量,tp_hash指明对于该类型的对象如何生成其hash值。
在PyTypeObject中指定的不同的操作信息也正是一种对象区别于另一种对象的关键所在。
在这些操作族中,有三组非常重要:
指向PyNumberMethods函数族,该族定义了一个数值对象应该支持的操作,典型对象如int,tp_as_number.nb_add指定了
对该对象进行加法操作时的具体行为。
指向PySequenceMethods函数族,该族定义了作为一个序列对象应该支持的操作,典型对象list.
指向PyMappingMethods函数族,该族定义了作为一个关联对象应该支持的操作,典型对象dict。
对一种类型来说,它完全可以同时定义三个函数族中的所有操作,只要定义相应的special_method
在Python中类型其实也是一个对象,类型的类对应Python内部的PyType_Type,它是所有class的class,在Python中称为metaclass,元类。
[object.h]
#ifdef Py_TRACE_REFS
#define _PyObject_EXTRA_INIT 0,0,
#else
#define _PyObject_EXTRA_INIT
#endif
#define PyObject_HEAD_INIT(type) _PyObject_EXTRA_INIT 1, type
\反斜杠把该定义延续到下一行,编译器将\分成的多个物理行转换为一个逻辑行,并删除\符号
#define预处理器指令以#号作为一行的开始,指令可以出现在源文件的任何地方,其定义从指令出现的地方到该文件末尾有效。
每行#define(逻辑行)都由3部分组成:
从宏变成最终替换文本的过程称为宏展开
在#define中使用参数可以创建外形和作用与函数类似的类函数宏
标签:log 通过 就是 ash blog 学习 完成 支持 dea
原文地址:http://www.cnblogs.com/huangke/p/7883347.html