python解释器[源代码层面]

1 PyDictObject

在c++中STL中的map是基于 RB-tree平衡二元树实现,搜索的时间复杂度为O(log2n)

Python中PyDictObject是基于散列表(散列函数)实现,搜索时间最优为O(1)

1.1 散列列表

问题:散列冲突:多个元素计算得到相同的哈希值

解决方法:

(1)开链法

(2)开放地址法:二次探测法(python中用的)

通过增加一个二次函数形式的偏移量来查找下一个空闲位置。哈希表的大小为m,一个元素的初始位置由哈希函数 h(x)决定。若发生冲突,则将元素插入到位置 (h(x)+i^2)mod  m处,其中i是探测的步数。探测序列是一个二次序列,例如:1^2,(-1)^2,2^2,(-2)^2在表中寻找下一个可用位置。

从一个位置出发可依次到达多个位置,形成“冲突探测链”(注意删除链上元素导致的断链,采用伪删除技术。)

1.2 定义

typedef struct {/* Cached hash code of me_key. */Py_hash_t me_hash; //存储me_key的散列值,维护该值是避免每次查询时重新计算PyObject *me_key;PyObject *me_value; /* This field is only meaningful for combined tables */
} PyDictKeyEntry;

entry生存周期的四种状态

  1. unused态:me_key/me_value都是null(entry在初始化的时候)。
  2. Active态:entry存储了键值对的状态。
  3. Dummy态:me_key指向dummy对象(伪删除)。
  4. Pending态:键!=空,值=空(仅拆分),尚未插入到拆分表中。
/* The ma_values pointer is NULL for a combined table* or points to an array of PyObject* for a split table*/
typedef struct {PyObject_HEADPy_ssize_t ma_used;    /*字典中项的数量*/
#ifdef Py_BUILD_COREuint64_t ma_version_tag; /*表示字典中对象版本*/
#elsePy_DEPRECATED(3.12) uint64_t ma_version_tag; /*表示字典中对象版本*/
#endif/*若ma_values为空,则表是结合的,键与值都存储在ma_keys中*//*若ma_values不为空,则表是分开的,键存储在ma_keys中,值存储在ma_values*/PyDictKeysObject *ma_keys; /*实际存储数据的哈希表,具体有两种存储方式*/PyDictValues *ma_values; //根据两种存储方式决定是否有值
} PyDictObject;
struct _dictkeysobject {Py_ssize_t dk_refcnt;//引用计数器数目/* Size of the hash table (dk_indices). It must be a power of 2. */uint8_t dk_log2_size; //这张哈希表的大小(最大存储的元素的数目)/* Size of the hash table (dk_indices) by bytes. */uint8_t dk_log2_index_bytes; //哈希表大小的字节数/* Kind of keys */uint8_t dk_kind; //类型的键/* Version number -- Reset to 0 by any modification to keys */uint32_t dk_version; //版本号/* Number of usable entries in dk_entries. */Py_ssize_t dk_usable; //在dk_entries中可用的数量/* Number of used entries in dk_entries. */Py_ssize_t dk_nentries; //在dk_entries中使用的数量(8个字节)/* Actual hash table of dk_size entries. It holds indices in dk_entries,or DKIX_EMPTY(-1) or DKIX_DUMMY(-2).Indices must be: 0 <= indice < USABLE_FRACTION(dk_size).The size in bytes of an indice depends on dk_size:- 1 byte if dk_size <= 0xff (char*)- 2 bytes if dk_size <= 0xffff (int16_t*)- 4 bytes if dk_size <= 0xffffffff (int32_t*)- 8 bytes otherwise (int64_t*)Dynamically sized, SIZEOF_VOID_P is minimum. */char dk_indices[];  /* 索引,一个元素一个字节 *//* "PyDictKeyEntry or PyDictUnicodeEntry dk_entries[USABLE_FRACTION(DK_SIZE(dk))];" array follows:see the DK_ENTRIES() macro */
};

1.3 python3.6+的存储方法

  1. 第一条key-value,计算inx=hash(key)%num,num是索引表长,索引表中存放着对于enries的偏移量。
  2. 依据indices[inx]的值(偏移量)存放Hash value=hash(key)、key、value
  3. 若该位置已经有元素,则根据冲突解决策略找下一个空闲的索引。
  4. 查找键的时候同样流程,并比较键与值来确定是否需要所需元素。

---------------后续有必要再继续写---------------------------------------------------

2 解释器

2.1组成

编译器:得到字节码的编译结果(import py文件、import compileall、内建函数compile后会得到.pyc文件)

虚拟机:执行字节码

执行环境:字典对象,维护运行过程中动态创建的变量和变量名与变量值的映射。

2.2执行脚本流程

1.完成模块的加载和链接

2.将源代码编译为PyCodeObject对象,并将其写入内存,使得CPU快速读取,加快程序运行

注:字节码与PyCodeObject对象的关系?

        PyCodeObject对象包含字符串,常量值,操作(字节码)等静态信息(运行时存储在PyCodeObject对象中,运行结束后存储在pyc文件)

3.从内存空间中读取指定并执行(虚拟机完成)

编译器与虚拟机在:python .dll

4.程序结束后根据调用的操作指令决定是否也将PyCodeObject对象写入硬盘,即.pyc文件或.pyo文件。

5.下一次再执行该脚本,则先检查本地是否有上述.pyc文件。如有,则执行。

2.3PyCodeObject

struct PyCodeObject{                                                    \PyObject_VAR_HEAD                                                          \\/* Note only the following fields are used in hash and/or comparisons      \*                                                                         \* - co_name                                                               \* - co_argcount                                                           \* - co_posonlyargcount                                                    \* - co_kwonlyargcount                                                     \* - co_nlocals                                                            \* - co_stacksize                                                          \* - co_flags                                                              \* - co_firstlineno                                                        \* - co_consts                                                             \* - co_names                                                              \* - co_localsplusnames                                                    \* This is done to preserve the name and line number for tracebacks        \* and debuggers; otherwise, constant de-duplication would collapse        \* identical functions/lambdas defined on different lines.                 \*/                                                                        \\/* These fields are set with provided values on new code objects. */       \\/* The hottest fields (in the eval loop) are grouped here at the top. */   \PyObject *co_consts;           /* list (constants used) */                 \PyObject *co_names;            /* list of strings (names used) */          \PyObject *co_exceptiontable;   /* Byte string encoding exception handling  \table */                                 \int co_flags;                  /* CO_..., see below */                     \\/* The rest are not so impactful on performance. */                        \int co_argcount;              /* #arguments, except *args */               \int co_posonlyargcount;       /* #positional only arguments */             \int co_kwonlyargcount;        /* #keyword only arguments */                \int co_stacksize;             /* #entries needed for evaluation stack */   \int co_firstlineno;           /* first source line number */               \\/* redundant values (derived from co_localsplusnames and                   \co_localspluskinds) */                                                  \int co_nlocalsplus;           /* number of local + cell + free variables */ \int co_framesize;             /* Size of frame in words */                 \int co_nlocals;               /* number of local variables */              \int co_ncellvars;             /* total number of cell variables */         \int co_nfreevars;             /* number of free variables */               \uint32_t co_version;          /* version number */                         \\PyObject *co_localsplusnames; /* tuple mapping offsets to names */         \PyObject *co_localspluskinds; /* Bytes mapping to local kinds (one byte    \per variable) */                          \PyObject *co_filename;        /* unicode (where it was loaded from) */     \PyObject *co_name;            /* unicode (name, for reference) */          \PyObject *co_qualname;        /* unicode (qualname, for reference) */      \PyObject *co_linetable;       /* bytes object that holds location info */  \PyObject *co_weakreflist;     /* to support weakrefs to code objects */    \_PyCoCached *_co_cached;      /* cached co_* attributes */                 \uint64_t _co_instrumentation_version; /* current instrumentation version */  \_PyCoMonitoringData *_co_monitoring; /* Monitoring data */                 \int _co_firsttraceable;       /* index of first traceable instruction */   \/* Scratch space for extra data relating to the code object.               \Type is a void* to keep the format private in codeobject.c to force     \people to go through the proper APIs. */                                \void *co_extra;                                                            \char co_code_adaptive[(SIZE)];                                             \
}

1.一个命名空间对应一个PyCodeObject对象。

2.类、函数、module都对应一个独立的命名空间(存在嵌套关系)。

2.4pyc文件

pyc文件=magic number( 区别python版本)+pyc文件的最后一次修改时间(再次加载时判断是否修改过)+PyCodeObject对象。

2.5创建pyc文件的具体过程(把PyCodeObject对象写入文件)

-------------------------待写

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/51521.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ARM 寻址方式(18)

立即寻址&#xff1a; 也叫作立即数寻址。 就是 立即数&#xff0c;本身就包含在了 指令当中。 举例&#xff1a; ADD R0, R0,#1 其中&#xff0c;#1 &#xff0c; 就是立即数&#xff0c;对于16进制的立即数&#xff0c; 需要在# 后加上 #0x. 寄存器寻址。 就是数据就在…

219. 存在重复元素 II【 力扣(LeetCode) 】

一、题目描述 给你一个整数数组 nums 和一个整数 k &#xff0c;判断数组中是否存在两个 不同的索引 i 和 j &#xff0c;满足 nums[i] nums[j] 且 abs(i - j) < k 。如果存在&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 二、测试用例 示例 1&…

多模态论文学习8.28

系列文章目录 文章目录 系列文章目录LAMM: Label Alignment for Multi-Modal Prompt Learning学习1、论文理解1、研究背景2、论文贡献3、方法框架4、研究思路5、实验6、限制 LAMM: Label Alignment for Multi-Modal Prompt Learning学习 1、论文理解 VL模型和下游任务之间的类…

单调栈,LeetCode 2289. 使数组按非递减顺序排列

一、题目 1、题目描述 给你一个下标从 0 开始的整数数组 nums 。在一步操作中&#xff0c;移除所有满足 nums[i - 1] > nums[i] 的 nums[i] &#xff0c;其中 0 < i < nums.length 。 重复执行步骤&#xff0c;直到 nums 变为 非递减 数组&#xff0c;返回所需执行的…

Amos百度云下载与安装 附图文安装教程

如大家所了解的&#xff0c;Amos是一款经常被运用在社会科学研究中的数据分析软件&#xff0c;尤其广泛用于人文社会科学领域的各种研究中。运用Amos&#xff0c;可以帮助研究人员使用结构方程模型 (SEM) 对他们收集到的数据进行分析与解释。 自用Amos 24安装包&#xff0c;可按…

数据结构与算法(循环链表,双向链表)

循环链表 最后一个元素指向首元素 带尾指针的循环链表合并 双向链表 双向链表:在单链表的每个结点里再增加一个指向其直接前驱的指针 域 prior &#xff0c;这样链表中就形成了有两个方向不同的链&#xff0c;故称为双向链表 双向链表插入操作 思路 代码 删除操作 思路 代…

一个很大的文件,文件的每一行是一个很大的数字,如果给你一个单机,内存比较小,存不了这么大的文件,但是硬盘是无限大的,如何对文件做一个排序输出

对于需要排序的大文件,尤其是当文件大小超过了可用内存时,可以采用外部排序算法。这里我描述一种基于归并排序思想的外部排序方法,它将大文件分割成多个小文件,在每个小文件上进行排序,然后再将这些排序好的小文件合并成一个有序的大文件。 以下是具体的步骤: 步骤 1: …

CTFHub SSRF靶场通关攻略(6-11)

FastCGI协议 首先写一个php的一句话木马&#xff0c;并进行base64编码 <?php eval($_POST[cmd]);?> 编码完成后把他写入shell.php文件中 echo "PD9waHAgQGV2YWwoJF9QT1NUW2NtZF0pOz8" | base64 -d > shell.php 使用Gopherus工具生成payload: 执命令 …

【工控】线扫相机小结

背景简介 我目前接触到的线扫相机有两种形式: 无采集卡,数据通过网线传输。 配备采集卡,使用PCIe接口。 第一种形式的数据通过网线传输,速度较慢,因此扫描和生成图像的速度都较慢,参数设置主要集中在相机本身。第二种形式的相机配备采集卡,通常速度更快,但由于相机和…

Clickhouse集群化(三)集群化部署

1. 准备 clickhouse支持副本和分片的能力&#xff0c;但是自身无法实现需要借助zookeeper或者clickhouse-keeper来实现不同节点之间数据同步&#xff0c;同时clickhouse的数据是最终一致性 。 2. Zookeeper 副本的写入流程 没有主从概念 平等地位 互为副本 2.1. 部署zookeep…

Mysql高级 [Linux版] 性能优化 数据库系统配置优化 和 MySQL的执行顺序 以及 Mysql执行引擎介绍

数据库系统配置优化 1、定义 数据库是基于操作系统的&#xff0c;目前大多数MySQL都是安装在linux系统之上&#xff0c;所以对于操作系统的一些参数配置也会影响到MySQL的性能&#xff0c;下面就列出一些常用的系统配置。 2、优化配置参数-操作系统 优化包括操作系统的优化及My…

C# UserControl、Dockpanel和DockContent、Cursor、

一、UserControl类 UserControl 是 .NET 中的一个基类&#xff0c;用于创建自定义控件&#xff0c;主要用于 Windows Forms 和 WPF。通过继承 UserControl&#xff0c;你可以设计和实现具有特定界面和功能的控件组件。UserControl 允许你将多个标准控件组合在一起&#xff0c;…

设备共享租赁小程序系统开发制作方案

设备共享租赁小程序系统让用户方便地租赁或出租各类设备&#xff0c;包括但不限于工具、电子产品、运动器材等&#xff0c;以满足临时使用需求&#xff0c;同时为设备所有者创造额外收益。 目标用户 个人用户&#xff1a;需要临时使用工具、车辆等设备的个人。 企业用户&#…

73 OSPF图解LSA(华三)

71 OSPF多区域实验(华三)-CSDN博客文章浏览阅读166次,点赞8次,收藏3次。实操https://blog.csdn.net/qq_56248592/article/details/141563010?spm=1001.2014.3001.5501 一 基础配置省略 上次的原图基础上扩展

C++ JAVA源码 HMAC计算 openssl 消息认证码计算 https消息防篡改 通信安全

签名和验签 把所有消息按顺序合并成一条信息&#xff0c;对这个信息用密钥进行签名。 签名信息通过 HTTP 头 Sign 传递&#xff0c;没有携带签名或者签名验证不通过的请求&#xff0c;将会被认为异常请求&#xff0c;并返回相应 code 码。 校验方法&#xff1a;根据 http请求…

重塑视频监控体验:WebRTC技术如何赋能智慧工厂视频高效管理场景

视频汇聚EasyCVR视频监控平台&#xff0c;作为一款智能视频监控综合管理平台&#xff0c;凭借其强大的视频融合汇聚能力和灵活的视频能力&#xff0c;在各行各业的应用中发挥着越来越重要的作用。 EasyCVR平台不仅兼容多种主流标准协议及私有协议/SDK的接入&#xff08;如&…

《探秘神经网络:人工智能的强大引擎》

在当今科技飞速发展的时代&#xff0c;人工智能已经成为了热门话题&#xff0c;而神经网络作为人工智能的重要组成部分&#xff0c;正发挥着越来越关键的作用。那么&#xff0c;什么是神经网络呢&#xff1f;它在人工智能中又有哪些令人瞩目的应用呢&#xff1f; 一、什么是神…

mysql高可用之组复制 (MGR)

目录 1 MySQL的主从复制介绍 2 组复制流程 3 组复制单主和多主模式 3.1 single-primary mode(单写或单主模式) 3.2 multi-primary mode(多写或多主模式) 4 实现mysql组复制 4.1 MASTER 1 4.2 MASTER 2 4.3 MASTER 3 4.4 MASTER 1 检验 1 MySQL的主从复制介绍 MySQL Group Rep…

使用Java将Google书签导出为JSON文件

背景介绍 Google书签是一个非常有用的工具&#xff0c;可以帮助我们管理和存储网页链接。然而&#xff0c;Google书签的导出文件格式是HTML文件&#xff0c;而在某些场景下&#xff0c;我们更希望将这些书签转换成更易于处理的JSON格式。本文将介绍如何使用Java和一些常见的库…

【Linux】初步识操作系统

linux专栏&#xff1a;《Linux入门系列》 系列文章&#xff1a;gdb-调试器初入门&#xff08;简单版使用&#xff09; 编辑器vim入门&#xff08;概念模式转换技巧&#xff09; 目录 1. 概念 2. 设计操作系统的目的 3. 定位&#xff1a;操作系统负责管理 4. 如何理解管理 …