python数据分析源码_python 统计分析

python数据分析源码_python 统计分析以后都在github更新,请参考CpythonInternals版本第一步克隆Cpython仓库到本地,切换到我当前的版本,我当前的版本号是3.8.0a0gitclonehttps://github.com/python/cpython.gitgitreset–hardab54b9a130c88f708077c2ef6c4963b632c132b…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

以后都在 github 更新,请参考 Cpython Internals

 

版本

第一步克隆 Cpython 仓库到本地, 切换到我当前的版本, 我当前的版本号是 3.8.0a0

git clone https://github.com/python/cpython.git
git reset --hard ab54b9a130c88f708077c2ef6c4963b632c132b3

PyObject

     PyObject 是 cpython 源码中最基本的 python 对象,记录了单个 Python 对象的任何信息, 他们的 memory layout 如下所示

python数据分析源码_python 统计分析

 

_PyObject_HEAD_EXTRA 在 Include/object.h 中第 72-83 行, 如果定义了 Py_TRACE_REFS 这个 marco, 他就是一对链表指针,指向上一个对象和下一个对象,不然的话(默认情况下),他就是一个空的值,猜测是 debug 或者其他特殊情况下开启这个选项

  ob_refcnt 是引用计数器,类型应该是一个无符号整型, 在cpython中垃圾回收中发挥作用,关于cpython的垃圾回收机制可以参考 python3 的垃圾回收机制
 

  ob_type 是真正指向这个 python 对象的指针,你看到的 tp_name, tp_print, getattr, setattr 等 python 对象共有的属性都能在这里找到

 

Ceval

执行一个 .py 文件会经历如下过程

python数据分析源码_python 统计分析

其实 ./python.exe(或者在命令行里敲入 python) 的时候包括了上面的编译器和解释器的全部过程,上图只是做了一个抽象

编译器将 py 文件转换成 python byte code(字节码), 里面是一个一个的 python 虚拟机指令

比如新建下面的文件 a.py

a = 3
print(a)

之后命令行输入

python3 -m dis a.py

结果:

  1           0 LOAD_CONST               0 (3)
              2 STORE_NAME               0 (a)

  2           4 LOAD_NAME                1 (print)
              6 LOAD_NAME                0 (a)
              8 CALL_FUNCTION            1
             10 POP_TOP
             12 LOAD_CONST               1 (None)
             14 RETURN_VALUE

 

左边的 1 和 2 是 第一行和第二行的意思,a.py 总共只有两行代码,所以只能看到 1 和 2

中间的是这一行是每一行代码对应的 python byte code

参考 Include/opcode.h 发现总共有 121 个 opcode, 所有的 python 源文件都会在内存中被编译器翻译成由 opcode 组成字节码指令集, 而 import 目录下会被保存成 pyc 文件,并缓存在执行目录,下次启动程序如果源代码没有修改过,则直接加载这个pyc文件,这个文件的存在可以加快 python 的加载速度

在 python 虚拟机中,解释器主要在一个很大的循环中,不停地读入 opcode, 并根据 opcode 执行对应的指令,当执行完所有指令虚拟机退出,程序也就结束了,这个主要的循环在 ceval.c 中,第 922 行的位置

main_loop:
    for (;;) {
        ...
            
        switch (opcode) {

        /* BEWARE!
           It is essential that any operation that fails must goto error
           and that all operation that succeed call [FAST_]DISPATCH() ! */

        case TARGET(NOP): {
            FAST_DISPATCH();
        }

        case TARGET(LOAD_FAST): {
            PyObject *value = GETLOCAL(oparg);
            if (value == NULL) {
                format_exc_check_arg(PyExc_UnboundLocalError,
                                     UNBOUNDLOCAL_ERROR_MSG,
                                     PyTuple_GetItem(co->co_varnames, oparg));
                goto error;
            }
            Py_INCREF(value);
            PUSH(value);
            FAST_DISPATCH();
        }

        case TARGET(LOAD_CONST): {
            PREDICTED(LOAD_CONST);
            PyObject *value = GETITEM(consts, oparg);
            Py_INCREF(value);
            PUSH(value);
            FAST_DISPATCH();
        }
        ...
    }
}

可以看到这个循环

我们来简单看下 LOAD_CONST 这个指令, 在上面的 switch case 里面,这个指令的代码总共5行, 第一行和第五行:

PREDICTED(LOAD_CONST);
FAST_DISPATCH();

 在 ceval.c 第 732 行可以找到 PREDICTED 的定义, 第 666 行可以找到 FAST_DISPATCH 的定义

#define FAST_DISPATCH() goto fast_next_opcode
...
#define PREDICTED(op)           PRED_##op:

## 和 # 号在 marco 里的作用可以参考 这篇 

 所以 LOAD_CONST 这个指令展开之后如下

case TARGET(LOAD_CONST): {
    PRED_LOAD_CONST:
    PyObject *value = GETITEM(consts, oparg);
    Py_INCREF(value);
    PUSH(value);
    goto fast_next_opcode;
}

可以看到,这个指令通过 GETITEM 从 oparg 中获取到了一个 python 对象的指针,这个指针的类型是  PyObject * 

Py_INCREF 作用是把这个 PyObject * 对象的引用计数器加一, 关于引用计数器可以参考 python3 的垃圾回收机制

PUSH 的作用是把这个刚刚创建的  PyObject *  push 到 当前的 frame 的 stack 上面,以便下一个指令从这个 stack 上面获取

关于 frame 可以参考 cpython 源码分析 PyFrameObject

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/172354.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 图标变成了一张白纸_电脑图标是白纸形式但能打开

    图标变成了一张白纸_电脑图标是白纸形式但能打开大家好,我是波导终结者。WIN10到现在也有些年头了,虽然好的不学学坏的,天天搞强制升级有些烦人,有时候新版本的BUG也比较致命,但是整体的性能,功能和稳定性上还是有飞跃性的提升。其实WIN10自带不少实用工具,而且兼容性和稳定性没得说,很多时候我们可以不必寻找第三方工具,省了很多钱,也提高了不少效率。今天就一起来看看吧。WIN10自带截图工具WIN10自带截图工具,虽然肯定不比专业的截图工具强,…

    2022年10月19日
  • Android 之 APP上架应用宝平台「建议收藏」

    这个是我自己要上架平台的一个应用,在此写了一篇博客为以后做铺垫。写的有错误请大家提出,我会及时更正,谢谢!下面首先肯定是要去腾讯开放平台上注册账号,不管是个人开发者还是企业的必须要通过资质审核否则你的应用不可能会上线的。上面的是前提工作,也是必要条件,下面的就是开始进行应用的上架步骤了。下面的步骤想必大家都知道怎么做了吧!其实还有需要注意的地方,那就是下面的版权证明,如果是个人开发者还好说,但是

  • 单片机定时器实验报告C语言,51单片机定时器实验报告.doc

    单片机定时器实验报告C语言,51单片机定时器实验报告.doc51单片机定时器实验报告51单片机定时器实验报告51单片机定时器实验实验内容:实验内容:编写程序使定时器0或者定时器1工作在方式1,定时50ms触发蜂鸣器。C语言程序#include#defineuintunsignedint#defineucahrunsignedcharsbitFM=P0^0;voidmain(){TMOD=0x01;TH0=(65535-50000)/256;…

  • redis RDB持久化方式的工作原理是怎样的_杜兰特挽留纳什

    redis RDB持久化方式的工作原理是怎样的_杜兰特挽留纳什我们已经知道对于一个企业级的redis架构来说,持久化是不可减少的,持久化主要是做灾难恢复,数据恢复,也可以归类到高可用的一个环节里面,比如你redis整个挂了,然后redis就不可用了,你要做的事情是让redis变得可用,尽快变得可用,重启redis,尽快让它对外提供服务。………

  • 视频直播技术详解之一:开篇

    视频直播技术详解之一:开篇随着互联网用户消费内容和交互方式的升级,支撑这些内容和交互方式的基础设施也正在悄悄发生变革。手机设备拍摄视频能力和网络的升级催生了大家对视频直播领域的关注,吸引了很多互联网创业者或者成熟企业进入该领域。七牛云作为一家以基础服务能力见长的云计算公司,于6月底发布了一个针对视频直播的实时流网络LiveNet和完整的直播云解决方案,很多开发者对这个网络和解决方案的细节和使用场景非常感兴趣

  • 更改nginx端口_nginx 端口映射

    更改nginx端口_nginx 端口映射Postedby撒得一地on2015年8月25日innginx笔记nginx相关文章在web服务器中,不管是Apache还是Nginx,这些服务器默认占用的端口都是80端口。但是,有时候80端口被占用,或者一些其他原因,我们需要这些服务工作在非80端口上,那么如何修改Nginx默认端口,使其占用8089端口(或者其它非80端口),方法步骤如下:1.首先修改nginx根目录下的配置文件n…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号