【python数据类型底层原理】

python 有动态的数据类型

x=1   
x='ssss'

这样的赋值可以连续操作而不报错。
因为变量内部= 值信息 + 类型额外信息 —> 动态数据类型

1 整型
python基于C编写,每一个对象都是伪C的语言结构体
整型 为一个指针 指向一个C的结构体

struct _longobject {
    long ob_refcnt;
    PyTypeObject *ob_type;
    size_t ob_size;
    long ob_digit[1];
};

ob_refcnt 为引用计数,协助pythonGC的
ob_type 将变量的类型编码
ob_size 接下来的数据成员大小
ob_digit 包含表示的实际整型值

存储一个整型有额外开销 pyobject_HEAD + 数字
C整型队形某个内存位置的标签,存储的字节会编码成整型
python实则为一个指针,指向包含该对象所有信息的某个内存位置(包含可转换为整型的字节)
自由动态编码,但是造成了额外的负担

2 列表 list
标准可变多元素容器
包含多个python对象的数据结构

typedef struct {
    PyObject_VAR_HEAD
    PyObject **ob_item;  //指针数组
    Py_ssize_t allocated;  //长度 申请内存的槽个数
} PyListObject;

如果一个数组中类型相同,那么每个对象自带的信息就会出现冗余(普通list)
数组包含一个自己的 head 加长度 加元素。元素指针指向连续的数据块(这个数据块是一个指针块),然后每个指针再指向一个完整的python对象
每次添加或者删除一个对象,需要重新分配数组(但是财通指数过分配,所以并不是每次都需要改变数组大小)
在这里插入图片描述

numpy为固定类型的数组
数据类型的结构体中包含head 数据 维度 步幅等数据,然后指向第一个元素的位置。后续根据步幅以及维度来寻找数据(如果为整型的话,指向的就是一个字节块?)
在这里插入图片描述

3 Dict(hashtable)
Cpython使用伪随机探测 的 hashtable作为字典的底层结构
只有可哈希的对象才能作为字典的键(可变类型均不可哈希,例如字典,集合,列表。不可变类型才能哈希)
复制或者遍历字典的操作中,最坏的复杂度 O(N)为 曾经达到的最大元素,而非现在的元素个数

python中 将 数组的 index 作为key的hash值,映射到数组值value。
解决哈希碰撞的方法:
1)开放寻址(python2使用这种方法):
碰撞时,通过一个 探测函数 计算下一个候选位置,如果冲突则继续通过探测函数寻找,直到空槽存放。
(线性探测再散列,二次探测再散列)

2)再hash法:
规定多个hash函数

3)链地址法:
关键字哈希值相同的记录存放在同一线性链表中,按照顺序遍历即可找到

4)公共溢出区:
碰撞时,新值置入溢出区

5)装填因子a:
a越小越容易碰撞
一个KV是一个entry
状态:unused active dummy(因为存在开放寻址法,存在探测链,删除链中间的值时其实是假删除)

4 set集合
与hashtable一样,基于hash对元素进行散列,只包含对键的引用没有对值的引用。

©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页