前言
cPython中,一个package、一个module,甚至一个function,都是一个类,每个类都有自己的Type类表示自己的class类型
Object
Object 所有类的C父类
Object是所有cpython中的类结构体定义的第一个成员,所有的Object都可以使用Object*指针访问Object的基本成员
/usr/include/python3.9d/object.h: 105
/* Nothing is actually declared to be a PyObject, but every pointer to
* a Python object can be cast to a PyObject*. This is inheritance built
* by hand. Similarly every pointer to a variable-size Python object can,
* in addition, be cast to PyVarObject*.
*/
typedef struct _object {
_PyObject_HEAD_EXTRA
Py_ssize_t ob_refcnt;
PyTypeObject *ob_type;
} PyObject;
- _PyObject_HEAD_EXTRA
- 空 暂时没有定义 定义在此将会影响所有类
- ob_refcnt
- 引用计数 cpython的内存释放通过引用计数+主动回收,两种,当一个类被另一个类指针指向时候,引用+1,当一个类减少一次指向时候引用-1,当引用为0时主动释放该类
- python中True、False、None是特殊的,这几个类在内存中永远只有一个实体,所有的True类的指向都是同一个实体
- ob_type
- 类 的定义,也就是 type(class)
下面是 在基类 Object 上的叠加套娃宏定义类描述了不同的类,对Object的使用,内存的布局
PyObject_VAR_HEAD
可变元素数量 比如 list/set 会使用的Object定义
也有很多明明是不可变元素数量类型,依然使用了这个结构体,比如Bool类型
/usr/include/python3.9d/object.h
/* PyObject_VAR_HEAD defines the initial segment of all variable-size
* container objects. These end with a declaration of an array with 1
* element, but enough space is malloc'ed so that the array actually
* has room for ob_size elements. Note that ob_size is an element count,
* not necessarily a byte count.
*/
#define PyObject_VAR_HEAD PyVarObject ob_base;
typedef struct {
PyObject ob_base;
Py_ssize_t ob_size; /* Number of items in variable part */
} PyVarObject;
- ob_base
- Object 本身,描述类的type和引用计数
- ob_size
- 包含元素的数量
内存布局
((PyObject*)ob_base->ob_base)->ob_refcnt
((PyObject*)ob_base->ob_base)->ob_type
ob_base->ob_size
PyObject_HEAD
普通的 没有成员的Object,就是一个Object
/usr/include/python3.9d/object.h
/* PyObject_HEAD defines the initial segment of every PyObject. */
#define PyObject_HEAD PyObject ob_base;
Type Object 类的描述
type(object) 返回的也是一个类成员,类的所有示例,如上面的PyObject结构体描述,都有一个指向PyTypeObject的指针,描述这个object属于哪个类
/usr/include/python3.9d/object.h
typedef struct _typeobject PyTypeObject;
struct _typeobject {
PyObject_VAR_HEAD
const char *tp_name; /* For printing, in format "<module>.<name>" */
Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */
/* Methods to implement standard operations */
destructor tp_dealloc;
Py_ssize_t tp_vectorcall_offset;
getattrfunc tp_getattr;
setattrfunc tp_setattr;
***
struct PyMethodDef *tp_methods;
struct PyMemberDef *tp_members;
struct PyGetSetDef *tp_getset;
struct _typeobject *tp_base;
***
PyObject *tp_bases;
***
- tp_name
- 类的名称
- tp_basicsize
- 类的结构体占用大小,对于
type object
则占用sizeof(_typeobject)
- 这个大小一定是超过
sizeof(PyObject)
的
- 类的结构体占用大小,对于
- tp_itemsize
- 成员的大小
- tp_methods
- 类中具有的方法
- tp_members
- 类中具有的类的属性 (区别与实例的属性 类的属性对于所有类实例都是共同的属性指针,值一致)
- tp_getset
- 使用@property @set 装饰的类的属性 使用函数读取或设置类的属性
- tp_base
- 类的第一个父类,python支持多继承,Surper不指定基类时候使用这个
- tp_bases
- 类的所有父类
等等,python的部分魔术方法,init、del,均定义在这里,任意一个Object即使不声明有这些魔术方法、这些也会占用内存空间,方法的指针设置为NULL
总结
所有的类
内存布局
PyObject 类指针(类的size存储在这里,私有成员影响size)、引用计数
私有成员
- 类.ob_base.ob_size = sizoef(类)
type 类
type类的布局 和上述一致 只是一个源码中已实现的类
内存布局
PyObject
Py_ssize_t 通常是可变成员类才有的,不过cpython里大多数类都使用了这个成员
type的私有成员,包含一个类的魔术方法、初始化、释放、方法、属性等
延申
Class True False None 这种在内存中始终只有一份的成员,适合使用is
判断,is
使用c指针内存地址==
进行判断,直接返回,速度更快,==
使用的类的计算函数有较多步骤
print((1 == 1) is True)
print(None is None)
print(type(1) is int)
class int2(int):
pass
print(type(int2(1)) is int)
print(type(int2(1)) is int2)
# python3 ./b.py
True
True
True
False
True