Python 虚拟机集合set实现原理及源码解析

Python 虚拟机集合 set 实现原理及源码解析

什么是 set

set 是 Python 中的一种基本数据类型,用于存储无序、不重复的元素集合。set 的特点是:

  • 无序性:set 中没有元素的顺序关系。
  • 互异性:set 中的元素都是唯一的,重复的元素会被自动忽略。

set 中可以存储任意类型的数据,例如数字、字符串、元组等不可变类型,但是不能存储可变类型,例如列表、集合、字典等。在 Python 中,set 使用了哈希表来实现。

哈希表的原理

哈希表是一种基于数组的数据结构,通过散列函数将关键字映射到数组中的一个位置,从而实现快速的数据查找。哈希表的核心思想是将原始数据进行多次加工,最终生成一个哈希值,然后将哈希值作为数组下标存储原始数据。在 Python 中,内置的哈希函数 hash() 可以将大部分对象转换为整数作为哈希值。

哈希表的主要优点是查找速度快,时间复杂度为 O(1),缺点是空间利用率低,因为可能存在哈希冲突,即不同的关键字生成相同的哈希值,需要额外的措施进行处理。Python 中的哈希表使用开放地址法来解决哈希冲突,具体是通过线性探测法、二次探测法或者双重哈希法等方式进行探测,直到找到空槽位为止。

set 的实现原理

当 Python 创建一个 set 对象时,会为该对象分配一块内存空间,该空间包含了实例对象的头信息和哈希表的指针 table。哈希表的实现是通过 C 语言中的 struct _setobject 结构体实现的,该结构体定义如下:

typedef struct _setobject {
   PyObject_HEAD
   /* 数据个数 */
   Py_ssize_t size;
   /* 哈希表元素个数 */
   Py_ssize_t used;
   /* 哈希表大小 */
   Py_ssize_t fill;
   /* 哈希表指针 */
   PyObject **table;
} PySetObject;

set 对象中,size 表示实例中元素的个数,used 表示哈希表中已经分配的槽位数,fill 表示哈希表的大小,table 是一个指向指针数组的指针,指向的每个元素都指向一个 HashEntry 结构体。

typedef struct {
   Py_hash_t hash;
   PyObject *key;
} HashEntry;

HashEntry 结构体包含了两个域,hash 表示该元素的哈希值,key 表示该元素的值。

set 中的操作分为两类,一类是对 set 对象本身的操作,例如向 set 中添加或者删除元素,另一类是对 set 中元素的操作,例如判断 set 中是否包含某个元素。

set 的源码解析

创建 set 实例

当我们使用以下语法创建一个 set 实例时:

s = set([1, 2, 3])

Python 调用 set() 函数来创建 set 实例,实际上是调用了 C 函数 set_new() 来创建一个新的 set 对象。该函数主要做了以下几件事情:

  1. 分配内存空间,包括头信息和哈希表指针。
  2. 设置头信息,包括类型信息和引用计数为 0。
  3. 初始化 PySetObject 结构体的成员变量,包括 sizeusedfilltable
  4. 将数据元素插入哈希表中。

添加元素到 set 中

当我们使用以下语法将元素添加到 set 中时:

s.add(4)

Python 调用 set_add() 函数来添加元素。该函数首先会检查要添加的元素在哈希表中是否存在,如果存在则返回,否则就新建一个 HashEntry 结构体,并将元素的哈希值和指针赋值给结构体的 hashkey 成员变量,然后将结构体插入到哈希表中。

从 set 中删除元素

当我们使用以下语法将元素从 set 中删除时:

s.remove(4)

Python 调用 set_discard() 函数来删除元素。该函数首先会根据元素的哈希值在哈希表中查找该元素是否存在,如果存在则删除元素,否则什么也不做。

判断元素是否在 set 中

当我们使用以下语法判断元素是否在 set 中时:

if 4 in s:
    print("元素在 set 中")

Python 调用 set_contains() 函数来判断元素是否在 set 中。该函数首先会根据元素的哈希值在哈希表中查找该元素是否存在,如果存在则返回 True,否则返回 False

示例说明

示例 1:使用 set 存储元素

如下代码展示了如何使用 set 存储元素,包括创建 set 实例和向 set 中添加元素:

# 创建 set 实例
s = set()
# 向 set 中添加元素
s.add(1)
s.add(2)
s.add(3)
# 打印 set 中的元素
print(s)  # 输出:{1, 2, 3}

示例 2:使用 set 进行元素去重

如下代码展示了如何使用 set 对列表元素进行去重:

# 定义一个包含重复元素的列表
lst = [1, 2, 2, 3, 3, 3, 4, 5, 5, 5]
# 将列表元素转换为 set,去重后再转换回列表
lst = list(set(lst))
# 打印去重后的列表
print(lst)  # 输出:[1, 2, 3, 4, 5]

以上示例说明了 set 的两个常见用途,一个是存储元素,另一个是进行元素去重。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python 虚拟机集合set实现原理及源码解析 - Python技术站

(0)
上一篇 2023年6月7日
下一篇 2023年6月7日

相关文章

  • 加载 .pkl 文件后出现 Python 错误“ValueError:无法识别加载的数组布局”

    【问题标题】:Python error after loading .pkl file “ValueError: Did not recognise loaded array layout”加载 .pkl 文件后出现 Python 错误“ValueError:无法识别加载的数组布局” 【发布时间】:2023-04-05 01:09:01 【问题描述】: 以下…

    Python开发 2023年4月6日
    00
  • 当 Python 3.5.2 调用 gsutil rsync 时返回错误,但从命令行可以

    【问题标题】:gsutil rsync returns error when called by Python 3.5.2, but okay from command line当 Python 3.5.2 调用 gsutil rsync 时返回错误,但从命令行可以 【发布时间】:2023-04-02 18:33:02 【问题描述】: 我有一个 gsutil…

    Python开发 2023年4月8日
    00
  • 关于Python ImportError: No module named 通用解决方法

    在Python编程中,经常会遇到ImportError: No module named xxx的错误,这个错误通常是由于Python无法找到所需的模块或包而导致的。本文将详细讲解关于Python ImportError: No module named 通用解决方法,包括检查模块是否安装、检查PYTHONPATH环境变量、检查sys.path路径、以及使用…

    python 2023年5月13日
    00
  • 不归路系列:Python入门之旅-一定要注意缩进!!!(推荐)

    不归路系列:Python入门之旅-一定要注意缩进!!! 一、缩进的重要性 在Python中,缩进是一种语法规则,它用来表示代码的块级别结构,是Python语言最重要的语法之一。缩进的作用是用来标示代码的层次结构,一般用4个空格或者1个制表符来表示,当然,两种不建议混用。 1.1 缩进的作用 Python中的代码块是通过缩进来表示的,每一级缩进代表一个嵌套层级…

    python 2023年5月13日
    00
  • 利用Python复制文件的9种方法总结

    标题:利用Python复制文件的9种方法总结 首先,需要明确Python中文件复制的基本方法:使用shutil模块中的copy()方法。下面开始介绍“利用Python复制文件的9种方法总结”: 1. 使用shutil模块中的copy()方法 可以通过Python的shutil模块中的copy()方法对文件进行复制。该方法接受两个参数,一个是源文件的路径,另一…

    python 2023年6月2日
    00
  • python list转置和前后反转的例子

    以下是详细讲解“Python列表转置和前后反转的例子”的完整攻略。 Python列表转置 在Python中,可以使用嵌套的列表来表示矩阵。如果要对矩阵进行转置,可以使用嵌套列表和for循环来实现。下面是一个示例,演示了如何使用列表转置: matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] transpose = [[row[…

    python 2023年5月13日
    00
  • 详解Python time库的使用

    详解Python time库的使用 time库是Python内置的库,用于处理时间和日期相关的函数和方法。在本篇攻略中,我们将详细讲解time库的使用,包括时间的格式化、时间戳等相关操作。 时间的表示方式 在Python中,时间有两种常见的表示方式: 时间元组(struct_time),包含年、月、日、时、分、秒等时间信息 时间戳(timestamp),表示…

    python 2023年6月2日
    00
  • python实现自动打卡小程序

    Python实现自动打卡小程序攻略 自动打卡是我们日常生活中非常重要的任务之一,使用Python可以方便地实现自动打卡小程序。本攻略将介绍使用Python实现自动打卡小程序的示例代码,包括数据获取、数据处理、自动化操作和示例。 步骤1:获取数据 在Python中,我们可以使用requests库获取打卡数据。以下是获取打卡数据的示例: import reque…

    python 2023年5月15日
    00
合作推广
合作推广
分享本页
返回顶部