python中字符串对象的实现

本文介绍了Python中字符串对象的内部结构,包括PyStringObject的组成,以及小字符串的内存管理。详细解析了创建字符串如's1 = 'abc''时的内存分配过程,并说明了小字符串的复用策略。此外,讨论了Python字符串搜索的实现,特别是find方法如何利用Boyer-Moore和Horspool算法的组合进行高效查找。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C中的字符串是一个以'\0'结尾的字符数组

python中的字符串对象有内部的PyStringObject表示。

结构:

typedef struct
{
    PyObject_VAR_HEAD;
    long ob_shash;
    int ob_sstate;
    char ob_sval[1];
}PyStringObject;

其中ob_shash是字符串的哈希,ob_sval包含大小为ob_size的字符串,以'\0'终止,ob_sval初始大小为1字节

ob_sval[0] = 0。ob_size位于PyObject_VAR_HEAD中,这位于object.h,ob_sstate表示字符串对象是否在待查字典中


s1 = 'abc'会发生什么?

调用内部C函数PyString_FromString,以下是伪代码

argument:stirng object :'abc'
returns :Python string object with ob_sval = 'abc'
PyString_FromString(string):
    size = length of string
    allocate string object + size for 'abc'.ob_sval will be of size:size+1
    copy string to ob_sval
    return object

可以看出每次使用新字符串时,都会分配一个新的字符串对象


在变量之间共享小字符串,减少了使用的内存量

小字符串就是大小为0-一个字节能够容纳的字符串,其实也就是字母了

静态全局变量interned是引用这些小字符串的字典,字符数组还引用长度为1字节的字符串,也就是字母

一些常量都在相应的头文件里面,这是用C实现的python

static PyStringObject * characters[UCHAR_MAX+1];
static PyObject *interned;

s2 = 'a'会发生什么?

包含“a”的字符串对象将添加到字典interned中,key是指向字符串对象的指针,值是相同的指针,新的字符串对象在字符数组中偏移量97的地方引用。所以说s3指向key为指向’a'的指针,value也为指向‘a'的指针的字符串对象

 


s3 = ’a'怎么办呢:


 

 s4 = ‘c'怎么办呢:

字符串搜索

一般我们用find方法,这个方法内部是用Boyer-Moore和Horspool算法的结合版本

我们将搜索字符串称为“ s”,将搜索字符串称为“ p”。s ='adcabcdbdabcabd'和p ='abcab'。“ n”是“ s”的长度,“ m”是“ p”的长度。n = 18且m = 5。

代码中的第一个检查是显而易见的,如果m> n,那么我们知道我们将无法找到索引,因此该函数立即返回-1,如下面的代码所示:

w = n -m;
if (w<0)
    return -1;

当m = 1时,代码每次一次通过“ s”一个字符,并在匹配时返回索引。在我们的示例中,mode = FAST_SEARCH,因为我们要查找的是索引中首先找到该字符串的索引,而不是找到该字符串的次数。

if (m <= 1)
{
    ...
    if (mode == FAST_COUNT) {
        ...
    } 
    else
    {
        for (i = 0; i < n; i++)
            if (s[i] == p[0])
                return i;
    }
    return -1;
}

而对于其他情况,m>1;第一步是创建一个压缩的Boyer-Moore delta 1表,在该步骤中将分配两个变量:“掩码”和“跳过”。

掩码”是一个32位的位掩码,使用字符的5个最低有效位作为关键字。它是使用字符串搜索“ p”生成的。这是一个Bloom筛选器,用于测试此字符串中是否存在字符。这确实非常快

位掩码的生成方式:

mlast = m-1;
for (mask = i = 0;i<mlast;i++)
{
    mask |= (1<<(p[i]&0x1f));
}
mask |= (1<<(p[mlast] & 0x1f));

Boyer-Moore算法:链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值