Python源码剖析 - Python中的整数对象

4 篇文章 0 订阅
订阅专栏

1. 不可变的PyIntObject

Python源码剖析 - 对象初探 我们对 PyIntObject 已经有了初步的了解。 Python 中的对象可以分为固定长度和可变长度两种类型。除此之外,也可以按照可变和不可变进行划分。

PyIntObject 则属于长度固定且不可变的对象。相比其他的对象而言,最简单,也最容易理解。

我们先来了解一下 PyIntObject 类型的类型信息,代码如下:

PyTypeObject PyInt_Type = {
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
    "int",
    sizeof(PyIntObject),
    0,
    (destructor)int_dealloc,                    /* tp_dealloc */
    (printfunc)int_print,                       /* tp_print */
    0,                                          /* tp_getattr */
    0,                                          /* tp_setattr */
    (cmpfunc)int_compare,                       /* tp_compare */
    (reprfunc)int_to_decimal_string,            /* tp_repr */
    &int_as_number,                             /* tp_as_number */
    0,                                          /* tp_as_sequence */
    0,                                          /* tp_as_mapping */
    (hashfunc)int_hash,                         /* tp_hash */
    0,                                          /* tp_call */
    (reprfunc)int_to_decimal_string,            /* tp_str */
    PyObject_GenericGetAttr,                    /* tp_getattro */
    0,                                          /* tp_setattro */
    0,                                          /* tp_as_buffer */
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
        Py_TPFLAGS_BASETYPE | Py_TPFLAGS_INT_SUBCLASS,          /* tp_flags */
    int_doc,                                    /* tp_doc */
    0,                                          /* tp_traverse */
    0,                                          /* tp_clear */
    0,                                          /* tp_richcompare */
    0,                                          /* tp_weaklistoffset */
    0,                                          /* tp_iter */
    0,                                          /* tp_iternext */
    int_methods,                                /* tp_methods */
    0,                                          /* tp_members */
    int_getset,                                 /* tp_getset */
    0,                                          /* tp_base */
    0,                                          /* tp_dict */
    0,                                          /* tp_descr_get */
    0,                                          /* tp_descr_set */
    0,                                          /* tp_dictoffset */
    0,                                          /* tp_init */
    0,                                          /* tp_alloc */
    int_new,                                    /* tp_new */
};

核心代码解释:

代码说明
PyVarObject_HEAD_INIT(&PyType_Type, 0)1. 设定ob_type指向PyInt_Type结构的地址 2.定长
“int”设定 tp_name
int_deallocPyIntObject对象的析构函数
int_printPyIntObject对象的标准输出函数
int_compare比较操作
int_to_decimal_string将整数转换为数字字符串
&int_as_number数学操作函数集合,如加减乘除等
int_hash计算该对象的hash值
int_methods对象成员函数的集合

2. PyIntObject对象创建三种方式

关于 PyIntObject 的对象创建过程,我们在 Python源码剖析 - 对象初探中已经做了初步的介绍,通过阅读源码我们可以发现有有以下三种方式,可以用来创建 PyIntObject 对象

PyAPI_FUNC(PyObject *) PyInt_FromString(char*, char**, int);
PyAPI_FUNC(PyObject *) PyInt_FromUnicode(Py_UNICODE*, Py_ssize_t, int);
PyAPI_FUNC(PyObject *) PyInt_FromLong(long);

也就是说,一个 PyIntObject 可以来源于 String、Unicode 和 Long 类型的变量。

PyObject *
PyInt_FromLong(long ival)
{
    register PyIntObject *v;
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
    if (-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS) {
        v = small_ints[ival + NSMALLNEGINTS];
        Py_INCREF(v);
#ifdef COUNT_ALLOCS
        if (ival >= 0)
            quick_int_allocs++;
        else 
            quick_neg_int_allocs++;
#endif
        return (PyObject *) v;
    }    
#endif
    if (free_list == NULL) {
        if ((free_list = fill_free_list()) == NULL)
            return NULL;
    }    
    /* Inline PyObject_New */
    v = free_list;
    free_list = (PyIntObject *)Py_TYPE(v);
    (void)PyObject_INIT(v, &PyInt_Type);
    v->ob_ival = ival;
    return (PyObject *) v;
}

从代码实现来看,如果是一个小整数,那么就直接增加对这个小整数对象的引用,否则,则需要从 free_list 中选取一个可用的对象,并将该对象的 ob_ival 设置为当前的数值。

接下来,我们详细介绍 PyIntObject 中对小整数的处理方式。

3. PyIntObject的小整数对象

在 Python 中,代码直接对小整数对象的范围进行了限定,即 [-5, 257)

#ifndef NSMALLPOSINTS
#define NSMALLPOSINTS           257
#endif
#ifndef NSMALLNEGINTS
#define NSMALLNEGINTS           5
#endif
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
/* References to small integers are saved in this array so that they
   can be shared.
   The integers that are saved are those in the range
   -NSMALLNEGINTS (inclusive) to NSMALLPOSINTS (not inclusive).
*/
static PyIntObject *small_ints[NSMALLNEGINTS + NSMALLPOSINTS];
#endif

这些小整数对象,类似于常量一样常驻内存中,并不会不释放,这样做的优点在于:

  • 使用效率高,这些小整数对象,像静态常量一样,直接拿来就可以用
  • 避免经常使用小整数导致内存操作效率降低 - 假设我们没有将小整数常驻内存,按照 Python 中其他对象的处理方式来处理,必然会导致 malloc() 和 free() 的频繁调用,引起大量内存碎片,严重影响 Python 的整体性

但是这样做有几个的问题:

  • 常量的设定,是一个经验值,你没办法预计在你的程序里,这个样的设置就是最优的
  • 修改代价大,如果你发现我对小整数的范围进行调整,你能做的唯一办法,就是对源码进行修改,并进行重新编译。

4. PyIntObject的大整数对象

对于小整数,Python 通过小整数对象池的方式来解决效率问题,那么对于其他整数对象,又是如何处理的呢。

其实与小整数类似,也是通过内存池技术,不同的是这个内存池中的数值并不是固定的,而是谁需要使用,就来申请,使用完了,则归还到池子中去。

struct _intblock {
    struct _intblock *next;
    PyIntObject objects[N_INTOBJECTS];
};

typedef struct _intblock PyIntBlock;

static PyIntBlock *block_list = NULL;
static PyIntObject *free_list = NULL;

static PyIntObject *
fill_free_list(void)
{
    PyIntObject *p, *q;
    /* Python's object allocator isn't appropriate for large blocks. */
    p = (PyIntObject *) PyMem_MALLOC(sizeof(PyIntBlock));
    if (p == NULL)
        return (PyIntObject *) PyErr_NoMemory();
    ((PyIntBlock *)p)->next = block_list;
    block_list = (PyIntBlock *)p;
    /* Link the int objects together, from rear to front, then return
       the address of the last int object in the block. */
    p = &((PyIntBlock *)p)->objects[0];
    q = p + N_INTOBJECTS;
    while (--q > p)
        Py_TYPE(q) = (struct _typeobject *)(q-1);
    Py_TYPE(q) = NULL;
    return p + N_INTOBJECTS - 1;
}

通过 block_listfree_list 两个指针来进行维护,free_list 是一个单向列表,维护 block_list 中所有可用的内存块。如果 block_list 不够用了,则调用 fill_free_list() 申请新的内存。

5. 更多内容

原文来自兔子先生网站:https://www.xtuz.net/detail-136.html

查看原文 >>> Python源码剖析 - Python中的整数对象

如果你对Python语言感兴趣,可以关注我,或者关注我的微信公众号:xtuz666

python整数程序
aiaias的博客
09-20 649
代码一: i = input('请输入一个三位以上的数字:') out = int(i)//100 print('输入:',i,'\n 输出其百为以上的数字为:',out) 代码二: x = input('请输入10个整数间空格相隔:') y = x.split(' ') z =list(map(int,y)) print('原始的数串:',z) print('降序后数串',sorted(z,reverse = True)) ...
python怎么定义一个整数_python整数实现
weixin_39618806的博客
11-29 2953
整数对象定义:typedef struct {PyObject_HEADlong ob_ival;} PyIntObject;可以看到仅多了一个long域ob_ival来保存整数。之所以用long,是因为这里用long最高的符号位作为溢出标记位。整数对象内存管理机制:小整数:在[ -NSMALLNEGINTS, NSMALLPOSINTS )范围内的整数 定义为小整数,缓存在对象,在Pytho...
python整型数据源码分析_python int的源码分析
weixin_40004960的博客
12-09 128
在intobject.h找到整数的定义Python整数对象的数据实际保存在ob_ival,是c的long类型。PyObject_HEAD就应该是整数对象的描述了。从源码的描述知道PyObject_HEAD定义了整数对象的初始化信息其typedef struct _typeobject{}PyTypeObject,PyTypeObject可以被认为对象的最通用,最原始的类,被其他整数,字...
python定义一个整数_[python 源码]整数对象的创建和维护
weixin_39612817的博客
12-05 372
刚开始学python时候,发现一个很迷惑的现象,一直到看了源码后才知道了:>>> a=6>>> b=6>>> a isbTrue想用同样的参数初始化两个对象,结果却是,这两个对象其实是同样的对象????逗我呢?>>> a=666>>> b=666>>> a isbFalse这又是怎么回事?为...
python输入整数的代码,Python检查整数输入
weixin_34805367的博客
11-29 243
I am trying to allow a user to input into my program, however when they enter a string my program fails. It is for a bigger program but was trying to correct the problem, I have so far:data = raw_inpu...
Python源码剖析-深度探索动态语言核心技术
专注游戏研发
03-09 3781
Python源码剖析-深度探索动态语言核心技术内容简介Python 总体架构Python源代码的组织 内容简介 为了更好地利用python语言,无论是python本身还是和C/C++配合使用,深刻理解python的运行原理都是非常重要的,本文以CPython源码为研究对象,深入剖析Python的实现。主要包含: Python内置对象 Python虚拟机 Python高级特性 本文参考: Python源码剖析一书 学习建议:唯有亲身尝试,才能深解其三昧。 在真实的源码和文章的描述相比较揣摩,动手捣鼓捣鼓
Python源码剖析-深度探索动态语言核心技术》-高清带标签
11-19
根据提供的标题、描述以及部分上下文内容,我们可以深入探讨与《Python源码剖析-深度探索动态语言核心技术》一书相关的几个关键知识点。 ### 关键知识点一:Python源代码的内部结构 《Python源码剖析-深度探索动态...
Python源码剖析
09-05
Python源码剖析》这本书是Python开发者进阶的宝贵资源,它深入探讨了Python语言的内部工作机制,旨在帮助读者理解Python的内在逻辑和设计哲学。本文将基于书的主题进行详细解析,涵盖Python源码的核心知识点。 ...
Python源码剖析笔记
05-06
### Python源码剖析笔记知识点梳理 #### C语言基础回顾 ##### 关于ELF文件 ELF(Executable and Linkable Format)文件是Linux下一种常见的可执行文件格式。它分为可执行文件和目标文件两种类型,其可执行文件...
Python源码剖析.docx
最新发布
02-17
### Python源码剖析知识点概述 #### 一、开篇:源码学习的重要性及Python工程师成长之路 - **源码学习的意义**:理解Python内部工作原理,有助于提高代码质量和开发效率。 - **Python工程师的成长**:“小菜”的...
python输入整数的代码_Python检查整数输入
weixin_39710594的博客
11-29 126
I am trying to allow a user to input into my program, however when they enter a string my program fails. It is for a bigger program but was trying to correct the problem, I have so far:data = raw_inpu...
Python源码解析-整数与引用计数器
l1345411028的博客
09-01 392
Python源码整数这个概念是通过PyLongObject对象实现的。这与python2不同,在python2,存在PyIntObject的对象,将整数类型区分为int与long。而在最新的源码,已经将int与long的类型统一。
Python源码整数对象底层解析
Lessen的博客
11-22 624
这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 欢迎使用Ma...
Python整数类型(int)详解
m0_74309242的博客
01-08 646
Python整数类型(int)详解
python定义一个整数变量_Python变量和数据类型详解
weixin_39968852的博客
11-23 6756
Python 变量类型变量存储在内存的值。这就意味着在创建变量时会在内存开辟一个空间。基于变量的数据类型,解释器会分配指定内存,并决定什么数据可以被存储在内存。因此,变量可以指定不同的数据类型,这些变量可以存储整数,小数或字符。变量赋值Python 的变量赋值不需要类型声明。每个变量在内存创建,都包括变量的标识,名称和数据这些信息。每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建...
python整数类型
吴大锤的专栏
08-13 8540
# -*- coding: utf-8 -*- # @Time : 2019/8/13 22:42 # @Author : Dapao # @Email : wxqian_wxq@163.com # @File : int_typr.py # @Software: PyCharm """ Pythonint类型 整数型有4种表达方式: 1、十进制:最普通的整数就是十进制形式的...
有趣的python:关于python整数类型对象
MapzChen土豆大仙的专栏
11-23 677
通过is运算符我们可以比较两个对象是否同一个a = 2 b = 1 + 1 a is b 返回一个True a = 1000 b = 999 + 1 a is b 返回一个False 两个相似的行为返回了不同的结果,可以看出来 python在对于整数的缓存上将某个范围内的整数当作成“简单整数”来看待,类似java的常量表,而不在这个范围的整数则是每次创建不同的
python定义一个整数_深入 Python (5) 创建整数对象
weixin_39959192的博客
12-05 690
A glance针对小整数的优化;小整数区间;ob_type 和全局整数类型对象 PyLong_TypeStart整数对象Python 最常用的对象,如果每用到一个整数对象就要进行一次对象的创建、销毁,那成本就太高了,Python 在底层对不同的整数区别对待,以提高效率。small int对于一些足够小的整数Python 会预先将他们创建好,并且常驻在解释器内存的 small_ints[]...
python定义一个整数变量_Python变量与常量
weixin_39893728的博客
11-23 2391
1、什么是变量a=1,其 a 就是变量名称,1 就是它的值。在程序运行过程,变量的值一般都会发生改变,内存会专门开辟一段空间,用来存放变量的值,而变量名将指向这个值所在的内存空间。与变量相对的就是常量,在程序运行过程,常量的值不会发生改变。2、变量的命名规范变量名只能是 字母、数字或下划线的任意组合变量名的第一个字符不能是数字以下关键字不能声明为变量名['and', 'as', 'asse...
Python源码剖析:内存管理与整数对象
总结来说,`PyInt_FromLong`是Python整数对象创建的关键,而Python的整体架构则展示了从源代码到执行的整个流程,包括词法分析、语法分析、编译和解释执行。了解这些基础知识对于提升Python编程技能和优化程序性能...
写文章

热门文章

  • Python语言的起源与发展 4571
  • Python语言的优点和缺点 1498
  • Python源码剖析 - 对象初探 227
  • Python源码剖析 - Python的总体架构 222
  • Python源码剖析 - Python中的整数对象 204

分类专栏

  • Python源码剖析 4篇
  • Python基础教程 2篇

最新文章

  • Python源码剖析 - Python中的字符串对象
  • Python语言的优点和缺点
  • Python语言的起源与发展
2020年6篇

目录

目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值

玻璃钢生产厂家大型的玻璃钢雕塑卡通玻璃钢雕塑户外会变色不商场中庭鱼形美陈吊饰效果图水泥玻璃钢花盆模具金华玻璃钢雕塑厂阜阳市玻璃钢雕塑新密玻璃钢仿铜雕塑价格园林玻璃钢花盆价格棒棒糖玻璃钢雕塑玻璃钢花盆底部处理办法吉安玻璃钢雕塑订做价格济宁砂岩玻璃钢雕塑商场美陈国庆定制梅州主题玻璃钢雕塑价格吉林小区玻璃钢雕塑价格四川主题商场美陈销售厂家玻璃钢海洋雕塑哪个靠谱百色玻璃钢花盆江苏玻璃钢雕塑私人定做安宁设计玻璃钢雕塑哪里好玻璃钢雕塑哪种品牌的好四川大型商场美陈批发价陕西公园玻璃钢雕塑生产厂家武汉玻璃钢雕塑艺术品邵阳玻璃钢价值观雕塑安康玻璃钢气球雕塑玻璃钢花盆模压滁州商场大型美陈济南公园玻璃钢雕塑生产厂家福建大型商场创意商业美陈风格香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化