版权声明:本文系原创,转发请注明出处,商业用途联系作者https://blog.csdn.net/wenxueliu/article/details/80919892

类型系统

一般对象是不能静态分配的,而 python 所有内建对象都是静态分配的

typedef struct _object {

_PyObject_HEAD_EXTRA

Py_ssize_t ob_refcnt;

struct _typeobject *ob_type;

} PyObject;

#ifdef Py_TRACE_REFS

/* Define pointers to support a doubly-linked list of all live heap objects. */

#define _PyObject_HEAD_EXTRA \

struct _object *_ob_next; \

struct _object *_ob_prev;

#define _PyObject_EXTRA_INIT 0, 0,

#else

#define _PyObject_HEAD_EXTRA

#define _PyObject_EXTRA_INIT

#endif

默认编译 Py_TRACE_REFS 没有定义,因此,实际为

//固定长度,如 int

typedef struct _object {

Py_ssize_t ob_refcnt; //很明显引用计数器

struct _typeobject *ob_type; //保存类型信息

} PyObject;

//可变长对象,如 string, list

typedef struct {

PyObject ob_base;

Py_ssize_t ob_size; //元素个数

} PyVarObject;

python 所有对象的头部都是 PyObject,因此,可以通过 PyObject 指针指向任何对象。

我们最熟悉的 list 的定义如下:

#define PyObject_VAR_HEAD PyVarObject ob_base;

typedef struct {

PyObject_VAR_HEAD

/* Vector of pointers to list elements. list[0] is ob_item[0], etc. */

PyObject **ob_item;

/* ob_item contains space for 'allocated' elements. The number

* currently in use is ob_size.

* Invariants:

* 0 <= ob_size <= allocated

* len(list) == ob_size

* ob_item == NULL implies ob_size == allocated == 0

* list.sort() temporarily sets allocated to -1 to detect mutations.

*

* Items must normally not be NULL, except during construction when

* the list is not yet visible outside the function that builds it.

*/

Py_ssize_t allocated;

} PyListObject;

据此,知道所有的对象都包含共同的 PyObject,不同对象之间的区别在哪里呢?

主要的区别在于不同的对象对应 C 中不同的结构体

typedef struct _typeobject {

PyObject_VAR_HEAD

const char *tp_name; /* For printing, in format "." */

Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */

/* Methods to implement standard operations */

destructor tp_dealloc;

printfunc tp_print;

getattrfunc tp_getattr;

setattrfunc tp_setattr;

PyAsyncMethods *tp_as_async; /* formerly known as tp_compare (Python 2)

or tp_reserved (Python 3) */

reprfunc tp_repr;

/* Method suites for standard classes */

PyNumberMethods *tp_as_number;

PySequenceMethods *tp_as_sequence;

PyMappingMethods *tp_as_mapping;

/* More standard operations (here for binary compatibility) */

hashfunc tp_hash;

ternaryfunc tp_call;

reprfunc tp_str;

getattrofunc tp_getattro;

setattrofunc tp_setattro;

/* Functions to access object as input/output buffer */

PyBufferProcs *tp_as_buffer;

/* Flags to define presence of optional/expanded features */

unsigned long tp_flags;

const char *tp_doc; /* Documentation string */

/* Assigned meaning in release 2.0 */

/* call function for all accessible objects */

traverseproc tp_traverse;

/* delete references to contained objects */

inquiry tp_clear;

/* Assigned meaning in release 2.1 */

/* rich comparisons */

richcmpfunc tp_richcompare;

/* weak reference enabler */

Py_ssize_t tp_weaklistoffset;

/* Iterators */

getiterfunc tp_iter;

iternextfunc tp_iternext;

/* Attribute descriptor and subclassing stuff */

struct PyMethodDef *tp_methods;

struct PyMemberDef *tp_members;

struct PyGetSetDef *tp_getset;

struct _typeobject *tp_base;

PyObject *tp_dict;

descrgetfunc tp_descr_get;

descrsetfunc tp_descr_set;

Py_ssize_t tp_dictoffset;

initproc tp_init;

allocfunc tp_alloc;

newfunc tp_new;

freefunc tp_free; /* Low-level free-memory routine */

inquiry tp_is_gc; /* For PyObject_IS_GC */

PyObject *tp_bases;

PyObject *tp_mro; /* method resolution order */

PyObject *tp_cache;

PyObject *tp_subclasses;

PyObject *tp_weaklist;

destructor tp_del;

/* Type attribute cache version tag. Added in version 2.6 */

unsigned int tp_version_tag;

destructor tp_finalize;

#ifdef COUNT_ALLOCS

/* these must be last and never explicitly initialized */

Py_ssize_t tp_allocs;

Py_ssize_t tp_frees;

Py_ssize_t tp_maxalloc;

struct _typeobject *tp_prev;

struct _typeobject *tp_next;

#endif

} PyTypeObject;

其中

tp_bases : 指向基类指针

tp_basicsize : 分配对象空间大小

tp_new : 创建对象时调用对应的函数

创建对象

tp_new 根据 tp_basicsize 分配内存

如果 tp_new 为 NULL,会向上找到到 tp_base

初始化

tp_init

对象创建

Python C API

分配 Py[type]_Type 对象

AOL(abstract Object Layer) : 形如 PyObject_*** 可以应用到任何 python 对象上,如 PyObject_New 来创建对象

COL(Concrete Object Layer) : 只作用某一类型对象,如 PyInt_FromLong(10)

>>> __builtins__.__dict__['int']

>>> a = int(10)

>>> a

10

>>> type(a)

>>> int.__base__

类型

PyTypeObject PyBaseObject_Type = {

PyVarObject_HEAD_INIT(&PyType_Type, 0)

"object", /* tp_name */

sizeof(PyObject), /* tp_basicsize */ 0, /* tp_itemsize */

object_dealloc, /* tp_dealloc */

0, /* tp_print */

0, /* tp_getattr */

0, /* tp_setattr */

0, /* tp_reserved */

object_repr, /* tp_repr */

0, /* tp_as_number */

0, /* tp_as_sequence */

0, /* tp_as_mapping */

(hashfunc)_Py_HashPointer, /* tp_hash */

0, /* tp_call */

object_str, /* tp_str */

PyObject_GenericGetAttr, /* tp_getattro */

PyObject_GenericSetAttr, /* tp_setattro */

0, /* tp_as_buffer */

Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */

PyDoc_STR("object()\n--\n\nThe most base type"), /* tp_doc */

0, /* tp_traverse */

0, /* tp_clear */

object_richcompare, /* tp_richcompare */

0, /* tp_weaklistoffset */

0, /* tp_iter */

0, /* tp_iternext */

object_methods, /* tp_methods */

0, /* tp_members */

object_getsets, /* tp_getset */

0, /* tp_base */

0, /* tp_dict */

0, /* tp_descr_get */

0, /* tp_descr_set */

0, /* tp_dictoffset */

object_init, /* tp_init */

PyType_GenericAlloc, /* tp_alloc */

object_new, /* tp_new */

PyObject_Del, /* tp_free */

};

我们在自定义类的时候,都会继承 object 类,而这个类对应的

C 结构体就是 PyBaseObject_Type,从其 tp_name 为 "object" 可知端倪。

在创建对象的时候,所有对象都会调用这里的 object_new 函数

对象的行为

在 PyTypeObject 中三个成员决定对象的行为

PyNumberMethods *tp_as_number;

PySequenceMethods *tp_as_sequence;

PyMappingMethods *tp_as_mapping;

PyNumberMethods : 数字操作,加减乘除

PySequenceMethods : 序列相关

PyMappingMethods : 关联对象

如果一个对象支持上述操作,对应的指针就不为 NULL。

对象类型

PyTypeObject PyType_Type = {

PyVarObject_HEAD_INIT(&PyType_Type, 0)

"type", /* tp_name */

sizeof(PyHeapTypeObject), /* tp_basicsize */

sizeof(PyMemberDef), /* tp_itemsize */

(destructor)type_dealloc, /* tp_dealloc */

0, /* tp_print */

0, /* tp_getattr */

0, /* tp_setattr */

0, /* tp_reserved */

(reprfunc)type_repr, /* tp_repr */

0, /* tp_as_number */

0, /* tp_as_sequence */

0, /* tp_as_mapping */

0, /* tp_hash */

(ternaryfunc)type_call, /* tp_call */

0, /* tp_str */

(getattrofunc)type_getattro, /* tp_getattro */

(setattrofunc)type_setattro, /* tp_setattro */

0, /* tp_as_buffer */

Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |

Py_TPFLAGS_BASETYPE | Py_TPFLAGS_TYPE_SUBCLASS, /* tp_flags */

type_doc, /* tp_doc */

(traverseproc)type_traverse, /* tp_traverse */

(inquiry)type_clear, /* tp_clear */

0, /* tp_richcompare */

offsetof(PyTypeObject, tp_weaklist), /* tp_weaklistoffset */

0, /* tp_iter */

0, /* tp_iternext */

type_methods, /* tp_methods */

type_members, /* tp_members */

type_getsets, /* tp_getset */

0, /* tp_base */

0, /* tp_dict */

0, /* tp_descr_get */

0, /* tp_descr_set */

offsetof(PyTypeObject, tp_dict), /* tp_dictoffset */

type_init, /* tp_init */

0, /* tp_alloc */

type_new, /* tp_new */

PyObject_GC_Del, /* tp_free */

(inquiry)type_is_gc, /* tp_is_gc */

};

总结:

所有的对象都一个 PyObject 指针头,而 PyObject 中包含 PyTypeObject

包含所有对象的基本信息

所有以 object 为基类的对象 : tp_base 指向 PyBaseObject_Type

所有对象类型: ob_type 指向 PyType_Type

PyBaseObject_Type 的 ob_type 也指向 PyType_Type

python 多态

所有对象都有一个头 PyObject,而 PyObject 的 ob_type 指向 PyType_Type

所有对象的类型通过其 ob_type 指向的 PyType_Type 获知其类型信息

PyObject* PyObject_Repr(PyObject *v) {

//...

res = (*v->ob_type->tp_repr)(v);

//...

}

不同类型的 v 的类型对应不同的 PyType_Type 对象,调用对应对象的

tp_repr 方法

引用计数

#define Py_INCREF(op) ( \

_Py_INC_REFTOTAL _Py_REF_DEBUG_COMMA \

((PyObject *)(op))->ob_refcnt++)

#define Py_DECREF(op) \

do { \

PyObject *_py_decref_tmp = (PyObject *)(op); \

if (_Py_DEC_REFTOTAL _Py_REF_DEBUG_COMMA \

--(_py_decref_tmp)->ob_refcnt != 0) \

_Py_CHECK_REFCNT(_py_decref_tmp) \

else \

_Py_Dealloc(_py_decref_tmp); \

} while (0)

#define _Py_Dealloc(op) ( \

_Py_INC_TPFREES(op) _Py_COUNT_ALLOCS_COMMA \

(*Py_TYPE(op)->tp_dealloc)((PyObject *)(op)))

Py_INCREF : 增加计数

Py_DECREF : 减少计数,但对象 ob_refcnt 为 0 时调用 tp_dealloc 方法释放内存

注:

python 中引用计数次数不超过 Py_ssize_t 指定的大小的限制

tp_dealloc 并不意味着会释放内存,而是将其返回内存池

#define Py_REFCNT(ob) (((PyObject*)(ob))->ob_refcnt)

#define _Py_NewReference(op) ( \

_Py_INC_TPALLOCS(op) _Py_COUNT_ALLOCS_COMMA \

_Py_INC_REFTOTAL _Py_REF_DEBUG_COMMA \

Py_REFCNT(op) = 1)

可见在初始化的时候,将 ob_refcnt 置为 1

python 新闻分析系统 源码_python 源码分析之类型系统相关推荐

  1. Python新冠疫情可视化分析系统 计算机专业毕业设计源码08504

    摘 要 文中首先对新冠疫情可视化分析的项目需求进行了背景分析,接着介绍了项目的总体设计思路,然后具体阐述了疫情数据库的设计.疫情数据的查询.疫情数据的展示,并分析了核心代码.文中利用MySQL数据库存 ...

  2. python运行不了程序代码_Python源码分析2 - 一个简单的Python程序的执行

    本文主要通过跟踪一个非常简单的Python程序的执行,简单讨论Python实现的基本框架和结构. 要执行Python程序如下,功能非常简单:从1加到10再打印出来 # test program sum ...

  3. springboot+校园新闻数据化系统-计算机毕设 附源码99293

    springboot+校园新闻数据化系统 目  录 摘要 1 1 绪论 1 1.1研究目的和意义 1 1.2选题背景和意义 1 1.3系统开发技术的特色 1 1.4springboot框架介绍 1 1 ...

  4. hadoop 红色旅游景点分析系统-计算机毕设 附源码91858

    hadoop 红色旅游景点分析系统 目  录 摘要 1 1 绪论 1 1.1研究背景 1 1.2研究内容 2 1.3Hadoop优点 3 1.4 Hadoop框架介绍 3 1.5论文结构与章节安排 4 ...

  5. 基于flask徐州市天气信息可视化分析系统-计算机毕设 附源码 04600

    基于flask徐州市天气信息可视化分析系统 摘 要 信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最 ...

  6. python有哪些码_Python字节码介绍

    Python部落(python.freelycode.com)组织翻译,禁止转载,欢迎转发. 了解Python字节码是什么,Python如何使用它来执行代码,以及了解它可以帮我们干什么. 如果你曾经编 ...

  7. python获取当前系统的日期_python怎么获取当前系统时间

    python获取当前系统时间,包括年月日,时分秒,主要通过Python中的datetime模块来实现. 下面我们就通过具体的代码示例,给大家详细介绍Python获取当前时间日期的实现方法. 代码示例如 ...

  8. jspm城市交通事故档案管理分析系统毕业设计(附源码、运行环境)

    登录界面管理 备案信息管理 事故登记管理 用户管理 案件分类管理 案件统计管理  免费赠送本源代码.数据库,请私信

  9. python新闻爬虫系统的功能_基于Scrapy框架的Python新闻爬虫

    一.开发背景 Python作为数据处理方面的一把好手,近年来的热度不断增长.网络爬虫可以说是Python最具代表性的应用之一,那么通过网络爬虫来学习Python以及网络和数据处理的相关内容可以说是再合 ...

最新文章

  1. NUnitForms 测试GUI应用程序的优秀工具
  2. 后台技术-JavaWeb项目初识
  3. java--面向对象(4)--黑马程序员
  4. dlna和miracast可以共存吗_AirPlay、DLNA、Miracast三大无线技术介绍
  5. vue 固定div 滚动_vue.js-div滚动条隐藏但有滚动效果的实现方法
  6. php柱状图实现年龄分布,考官雅思写作小作文满分范文 柱状图:年龄分布
  7. 玩转Linux文件描述符和重定向
  8. Confluence wiki 使用记录
  9. 【BZOJ4521】手机号码,数位dp
  10. 基于op07的k型热电偶测量电路_基于OP07和LTC1543温度采集模块的设计
  11. 爱因斯坦求和约定在Python扩展库Numpy中的实现
  12. 买入股票后必须遵守的八项原则
  13. Python进阶(九)常用高级函数Counter、defaultdict、nametuple、map、reduce、filter、groupby
  14. mac 10.9 安装 mysql_mac 下安装 mysql (蛋疼)
  15. 常见十四种的Java算法
  16. Tarjan算法详解
  17. 海外抖音推荐算法,玩转tiktok短视频内容运营
  18. WMPF微信小程序框架 微信刷脸登录 获取openId 授权获取手机号 快速接入 快速集成
  19. Linux下U盘变成只读
  20. java小项目之:植物大战僵尸,这个僵尸不太冷!内附素材源码

热门文章

  1. 在图书馆学习红宝书的一天(二)· 慢慢看原型、原型链就看懂了~
  2. javax.management.InstanceNotFoundException: com.alibaba.druid:type=DruidStatService ERROR com.aliba
  3. 设置了hover伪类中有cursor:hand但是没有效果
  4. IT人士运动方式选择建议
  5. mybatisnet - 1 获取 mybatisnet
  6. 技术人员为什么应该参加社区活动?
  7. poj 3308(最小割求解最小点权覆盖)
  8. NYOJ 752 又见回文串
  9. Golang的模板与渲染
  10. 打分排序系统漫谈1 - 时间衰减