最近突然涌起兴趣去阅读 CPython 源码,网上也看了不少解析的文章,后来网上看到《Python源码剖析》评价不错,可惜现在已经绝版,只能从豆瓣阅读购买了一本电子书观摩 。

我从网上下载的是最新的 Python 2.7 源码,这本书配套的解说代码是 Python 2.5 的,这是一个遗憾,但是大体上相差不大,刚好昨天遇到一处。

昨天看到 Python int 实现的原理,这里不详细表述,有兴趣的可以去看看书。其中整数加法 (int_add) 的实现,虽然代码只有几行,但是其中隐藏的知识点还是非常多的,花了点时间回顾了一些基础知识,在这里也简单总结下。

以下是 2.5 里面加法的实现,也是书中提供的例子,这里直接引用过来作为参考对比,注释是作者加入的。

static PyObject* int_add(PyIntObject *v, PyIntObject *w)

{

register long a, b, x;

CONVERT_TO_LONG(v, a);

CONVERT_TO_LONG(w, b);

x = a + b;

//[1] : 检查加法结果是否溢出

if ((x^a) >= 0 || (x^b) >= 0)

return PyInt_FromLong(x);

return PyLong_Type.tp_as_number->nb_add((PyObject *)v, (PyObject *)w);

}

下面是 2.7 中的代码对比,大体都没有变化:

static PyObject *

int_add(PyIntObject *v, PyIntObject *w)

{

register long a, b, x;

CONVERT_TO_LONG(v, a);

CONVERT_TO_LONG(w, b);

/* casts in the line below avoid undefined behaviour on overflow */

x = (long)((unsigned long)a + b);

if ((x^a) >= 0 || (x^b) >= 0)

return PyInt_FromLong(x);

return PyLong_Type.tp_as_number->nb_add((PyObject *)v, (PyObject *)w);

}

在此之前,先简单介绍下上面的逻辑:

1)首先 int_add 函数是 Python 中 int 加法的实现函数,参数是两个 Python 整数对象,PyIntObject;

2)接着使用预先定义好的宏(不是重点,这里不具体展开),从整数对象中取出 value,这个value就是整数的值,类型是 long;

3)接下来做整数加法,判断是否溢出,如果没有发生溢出,则将新建一个整数对象,最后结果返回;

4)如果加法过程中发生溢出,则使用更长的类型(PyLong_Type)来做这个加法运算;

这个函数的精髓在与加法的处理,不是简单求和返回,可以看出 2.5 和 2.7代码的区别:

// 2.5

x = a + b;

// 2.7

x = (long)((unsigned long)a + b);

为什么 2.7 要搞得怎么复杂,又是转换成 unsigned long 最后又转换为 long,实际上原因是因为一个历史包袱,在C语言的定义中有符号数(signed)的加法溢出是 undefined behavior,所以这里先变成无符号数的加法,如果溢出就是简单做个截断(取模)。注意,无符号数和有符号数运算,有符号数会隐式转换成无符号数。

接下来我们看对溢出额判断,(x^a) >= 0 || (x^b) >= 0,为什么使用异或来判断。这里先梳理下,什么情况下会发生加法溢出:

1)如果两个不同符号的数字相加,不会发生溢出,比如 5 + (-128);

2)如果两个相同符号的数字相加,可能会发生溢出,比如正正相加溢出后变成负数,负负相加后变成整数;

这里实际上就是利用了这两点来作为判断依据,如果加法运算结果和原来的任意一个数字符号一致就没有溢出,使用异或来判断性能更好。关于溢出的判断还有其他方法,网上也有不少小伙伴提供了更多思路。

这里还有一个隐含的点,在 Python 里整数对象是不可变的,这个要注意,相加之后是返回一个新的对象:

>>> a = 1

>>> id(a)

38821992L

>>> a += 1

>>> id(a)

38821968L

继续看书。

python简单代码加法-CPython 源码中整数加法的实现相关推荐

  1. python字符串代码对象_Python源码剖析 - Python中的字符串对象

    1. 前言 我们已经在 [Python中的整数对象] 章节中对定长对象进行了详细的讲解,接下来我们将介绍变长对象,而字符串类型,则是这类对象的典型代表. 这里必须先引入一个概念: Python 中的变 ...

  2. Python内置函数的源码中方法只有pass占位符说明 Docs

    pass python定义函数,必须有函数体,否则编译就会报错.函数体用一句pass占位是防止报错,并且不会有任何动作.内置函数中使用pass的情况如下: 父类中声明函数,但不声明实现,由继承的子类进 ...

  3. 设计模式 笔记4 | 简单工厂模式 在源码中的应用 | Calendar 日历 | 源码浅析 | 使用总结 | 建造者模式

    文章目录 一.Calendar 日历类 1.1 内部属性 1.2 设置时间属性值 1.3 获取时间属性 1.4 使用 Calander 计算时间 二.Calender 类中的设计模式 2.1 简单工厂 ...

  4. python程序代码解析_Python源码分析3 – 词法分析器PyTokenizer

    Introduction 上次我们分析了Python中执行程序可分为5个步骤: Tokenizer进行词法分析,把源程序分解为Token Parser根据Token创建CST CST被转换为AST A ...

  5. python简单代码加法-Python tkinter实现简单加法计算器代码实例

    tkinter 是 Python 的标准 GUI 库.Python 使用 tkinter 可以快速的创建 GUI 应用程序.由于 tkinter 是内置到 python 的安装包中.只要安装好 Pyt ...

  6. 70个python项目代码_python项目实例源码

    #_*_ coding:utf-8 _*_ from tkinter import * importrandomimporttimeimporttkinter.messagebox#俄罗斯方块界面的高 ...

  7. android 静态工厂方法,Android 源码中的静态工厂方法

    我们知道工厂模式有三兄弟,通常我们说的工厂模式指的是工厂方法模式,它的应用频率最高.本篇博客分享的简单工厂模式是工厂方法模式的"小弟",确切的来讲它不属于设计模式,而是一种方法.此 ...

  8. python源码图片_初学者用python爬凡客图片的源码

    python学习最大的动力就是能写出一些可以运行的代码.感觉python真是的很强大. 下边的这部分python代码是我用来爬凡客T的图片,代码是初学阶段写的,比较简陋,没做修改,之前是可以用的.翻出 ...

  9. 编写Android.mk把Android studio项目编译到AOSP源码中

    前言: 在工作,我们利用Android studio开发apk是非常方便的,当我们要把工程代码放在android 源码中编译的时候,需要我们自己编写Andorid.mk 文件.以下内容是对Androi ...

最新文章

  1. Spring对JNDI的支持方法
  2. java中map的put方法,Java TreeMap put()方法
  3. 【MySQL 】学习笔记千行总结
  4. mysql查看日志命令_面对成百上千台服务器产生的日志,试试这款轻量级日志搬运神器!...
  5. 上清华到底有多难?清华大学保送生的数学试题了解一下
  6. 汇编语言---子程序设计举例(两组数据相加)
  7. 为什么老司机开车都不快?
  8. 怎样追求心仪的女孩子
  9. linux常用目录操作命令
  10. Vue3学习之第四节:setup()中使用watch、watchEffect 函数
  11. php 地区表设计,php消息表设计
  12. Android adb 命令大全
  13. whistle抓包工具学习
  14. 存储过程和函数的操作
  15. 利用poi3.8中SXSSFWorkbook实现大数据量导出excel
  16. 抖音记事本代码html,抖音上用记事本编写爱心小程序教程
  17. Tracking 1.3 Online Trackers
  18. 物联网操作系统Zephyr(入门篇)之1.0 Zephyr简介
  19. 苹果域对应关系 Manifest.db文件解析
  20. 道友自诉:入职中软一个月(外包华为)就离职了!

热门文章

  1. 总结ThinkPHP使用技巧经验分享(四)
  2. 虚拟化技术中,为什么说容器技术暂时将不会取代虚拟机模式
  3. 一道并查集的(坑)题:关闭农场closing the farm
  4. nagios 监控shell脚本
  5. ueditor图片上传,网络连接错误的解决方案
  6. 零基础学python看什么书-转行零基础该如何学习python?很庆幸,三年前的我选对了...
  7. pythonweb开发-如何用Python做Web开发?——Django环境配置
  8. python自学网址-关于python学习,最系统的学习网站看这里
  9. python在线-python+在线
  10. python读文件路径-在Python中按路径读取数据文件的几种方式