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

yizhihongxing

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

1. 集合概述

在 Python 中,集合(set)是一种不允许重复元素的数据类型。它的实现原理主要由哈希表和二叉树两部分组成。集合的基本操作包括add()remove()union()intersection()等。

Set 中的元素必须是可哈希的,哈希算法用于将元素映射到哈希表中,从而实现 O(1) 的查找操作。当哈希冲突时,Python 使用二叉树来解决冲突。

2. 集合创建

创建集合有两种方式:使用set()函数或使用花括号 {}

# 使用 set() 函数创建集合
s1 = set([1, 2, 3])
print(s1)
s2 = set('python')
print(s2)

# 使用 {} 创建集合
s3 = {1, 2, 3}
print(s3)

输出结果:

{1, 2, 3}
{'p', 'y', 't', 'h', 'o', 'n'}
{1, 2, 3}

3. 集合方法

(1)add(el)

用于将元素添加到集合中,如果集合中已经存在该元素,则不做任何修改。

s = {1, 2, 3}
s.add(4)
s.add(2)
print(s)

输出结果:

{1, 2, 3, 4}

(2)remove(el)

用于删除集合中的元素,如果元素不在集合中,则抛出KeyError异常。

s = {1, 2, 3}
s.remove(2)
print(s)

输出结果:

{1, 3}

(3)union(set)

用于合并两个集合。

s1 = {1, 2, 3}
s2 = {3, 4, 5}
s3 = s1.union(s2)
print(s3)

输出结果:

{1, 2, 3, 4, 5}

(4)intersection(set)

用于求两个集合的交集。

s1 = {1, 2, 3}
s2 = {3, 4, 5}
s3 = s1.intersection(s2)
print(s3)

输出结果:

{3}

4. 集合源码分析

Python 使用 setobject 结构体来表示集合对象。

typedef struct _setobject {
    PyObject_HEAD
    Py_ssize_t used;            /* # 索引表中已经使用的元素 */
    Py_ssize_t size;            /* # 索引表中可以使用的元素,size <= used */
    PyObject *table;            /* # 索引表 */
    /* # 哈希表总共分了 80 个桶,最多存 7453 个元素 */
    Py_hash_t hash;
} setobject;

集合中的元素和对应的哈希值保存在 table 中。table 实际上是一个由多个指针组成的数组,每个指针指向一个哈希冲突链表的头结点。每个节点又保存了元素、哈希值和指向下一个节点的指针。

5. 集合遍历

s = {1, 2, 3}
for el in s:
    print(el)

输出结果:

1
2
3

利用 Python 的迭代器(Iterator)机制,可以更加底层地遍历集合中的元素。

/* 在 setobject 结构体中定义了 PySetIterObject 迭代器 */
typedef struct {
    PyObject_HEAD
    Py_ssize_t it_index;            /* # 当前迭代器所在的桶的索引值 */
    PyObject *it_set;               /* # 当前迭代器操作的集合对象 */
    PyObject *it_value;             /* # 当前迭代器返回的元素 */
    Py_hash_t *it_hash_buf;         /* # 暂存哈希值的数组 */
} PySetIterObject;

/* setobject 结构体中定义了一个 PyHeapTypeObject 对象,其 ob_type 指向 PySet_Type */
typedef struct {
    PyVarObject_HEAD
    PySetObject set;                /* # 存放集合对象的 setobject 结构体 */
} PySet_T;

/* 在 PySet_Type 对象中定义了 tp_iter 函数 */
static PyObject *
set_iter(PyObject *so)
{
    PySetObject *so1 = (PySetObject *)so;
    PySetIterObject *it;

    it = PyObject_GC_New(PySetIterObject, &PySetIter_Type);
    if (it == NULL)
        return NULL;
    Py_INCREF(so);
    it->it_set = so;
    it->it_index = 0;
    it->it_value = NULL;
    if (so1->fill >= 0 && so1->used > 0) {
        it->it_hash_buf = (Py_hash_t *)
            PyMem_Malloc(sizeof(Py_hash_t) * so1->used);
        if (it->it_hash_buf == NULL) {
            PyErr_NoMemory();
            Py_DECREF(it);
            return NULL;
        }
        set_table_fill(so1);
        fill_it_hash_buf(it->it_hash_buf, so1);
    }
    else {
        it->it_hash_buf = NULL;
    }
    PyObject_GC_Track(it);
    return (PyObject *) it;
}

可以发现,集合的迭代器的实现方式也是通过遍历 table 中的元素来完成的。没有像列表和元组那样维护一个线性的结构。

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

(0)
上一篇 2023年5月13日
下一篇 2023年5月13日

相关文章

  • python命令 -u参数用法解析

    让我来详细讲解一下“python命令 -u参数用法解析”。 什么是 -u 参数 在Python命令行中,-u参数表示“将标准输出和标准错误输出直接输出。不进行缓冲”。在默认情况下,Python会将输出信息缓存,然后一次性输出。使用-u参数可以避免这种缓存,直接输出信息。 -u 参数的使用场景 通常,我们使用Python脚本或Python库时,会调用print…

    python 2023年6月2日
    00
  • pyinstaller打包opencv和numpy程序运行错误解决

    以下是关于“pyinstaller打包opencv和numpy程序运行错误解决”的完整攻略: 问题描述 在使用 PyInstaller 打包包含 OpenCV 和 NumPy 库的 Python 程序时,可能会出现行错误的情况。本文将介绍如何解决这些错误。 解决方法 1. 安装Installer 首先,需要安装 PyInstaller。可以使用 pip 命令…

    python 2023年5月13日
    00
  • python如何使用正则表达式的前向、后向搜索及前向搜索否定模式详解

    Python如何使用正则表达式的前向、后向搜索及前向搜索否定模式详解 在Python中,正则表达式是一种强的文本处理工具,可以用于字符串匹配、替换、分割等操作。正则表达中的前向搜索、后向搜索及前搜索否定模式是一些高级的正则表达式技巧,可以帮助我们更加活地处理文本数据。本攻略将详讲解Python如何使用正则表达式的前向、后向搜索及前向搜索否定式,包括如何使用正…

    python 2023年5月14日
    00
  • Python爬虫之爬取我爱我家二手房数据

    Python爬虫之爬取我爱我家二手房数据 在本攻略中,我们将介绍如何使用Python爬虫爬取我爱我家二手房数据,并提供一些示例。 步骤1:分析网页结构 在爬取我爱我家二手房数据之前,我们需要分析网页结构。我们可以使用浏览器开发者工具分析网页结构,也可以使用其他工具分析网页结构。 以下是一个示例,用于分析网页结构: import requests from b…

    python 2023年5月15日
    00
  • python实现浪漫的烟花秀

    Python 实现浪漫的烟花秀攻略 近年来,Python 逐渐流行起来,并被应用于各种领域。其中,Python 也可以用来制作浪漫的烟花秀特效。下面是 Python 实现浪漫的烟花秀的完整攻略: 引用必要的库 在终端中输入以下命令,下载需要的库: pip3 install pygame pip3 install random 其中,pygame 是 Pyth…

    python 2023年6月3日
    00
  • python删除csv文件的行列

    Python删除CSV文件的行列 在Python中,我们可以使用pandas库来删除CSV文件的行列。下面将介绍如何通过pandas库删除CSV文件的行列。 安装pandas库 在开始之前,我们需要先确保已经安装了pandas库。如果没有安装,可以通过以下命令在命令行中进行安装: pip install pandas 删除CSV文件的行 我们可以通过以下步骤…

    python 2023年6月3日
    00
  • python操作excel的方法

    现在我来详细讲解一下Python操作Excel文件的方法,包括如何读取、写入、创建、编辑和修改Excel文件。本文主要介绍两种解决方案:使用开源库xlrd和openpyxl。 读取Excel文件 使用xlrd库 xlrd库是Python读取Excel的一个常用库。它最适合读取.xls文件,但不支持读取.xlsx文件。下面是读取Excel文件的例子: impo…

    python 2023年5月13日
    00
  • python pyinstaller库

    简要 pyinstaller模块主要用于python代码打包成exe程序直接使用,这样在其它电脑上即使没有python环境也是可以运行的。 用法 一.安装 pyinstaller属于第三方库,因此在使用的时候需提前安装 pip install pyinstaller 二.配置spec文件 1.配置生成exe程序文件夹 (1)如果不熟悉spec配置内容,可以在…

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