PyStringObject效率相关的问题

本文探讨了Python中字符串连接的不同方法及其效率对比。介绍了通过“+”操作符与使用PyStringObject对象的join方法进行字符串连接的过程,并分析了各自在内存管理和性能上的优劣。

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

                      PyStringObject效率相关的问题

 

 在Python中又一个举足轻重的问题:字符串连接问题。字符串连接有两种方式:(1)通过“+”对字符串进行连接

(2)利用PyStringObject对象的join操作来对存储在list或tuple中的一组

PyStringObject对象进行连接操作。

 

(1)法效率比较低,因为Python中字符串对象是一个不可变的对象,当我们进行“+”操作时,我们就得从新申请一个新的PyStringObject对象。如果我们要进行N个字符串对象的连接,我们我要进行N-1次内存的申请和内存搬运的工作,显然,效率是十分底下的。使用(2)法可解决这个问题。

下面看下源码: 

 

Static PyObject * string_concat(register PyStringObject *a, register PyStringObject *bb)

{

Register Py_ssize_t size ;

Register PyStringObject *op ;

If(  ! PyString_Check(bb))

{

   PyErr_Format(PyExc_TypeError,“cannot concatenate ‘str’and

   ‘%.200s’objects”, bb->ob_type->tp_name);

   Return NULL ;

}

# define b ((PyStringObject*)bb)

//如果a或bb是指向空字符串对象的指针

If( (a->ob_size==0 || b->ob_size==0)&&

    PyString_CheckExact(a)&&PyString_CheckExact(b))

{

    If( a->ob_size == 0 )

    {

        Py_INCREF(bb) ;

        Return bb ;

    }

    Py_INCREF(a) ;

    Return (PyObject*)a;

}

Size = a->ob_size + b->ob_size ;//字符串连接后的长度size

If( a->size<0||b->size<0||a->ob_size+b->ob_size > PY_SSIZE_T_MAX)

{

    PyErr_SetString(PyExc_OverflowError, “string are too large”) ;

Return NULL ;

}

/*创建新的PyStringObject对象,其维护的用于存储字符的内存长度为

Size */

  Op = (PyStringObject*)PyObject_MALLOC(sizeof(PyStringObject)+size);

  PyObject_INIT_VAR(op,&PyString_Type,size);

  Op->ob_shash = -1 ;

  Op->ob_sstate = SSTATE_NOT_INTERNED ;

  将a和b中的字符拷贝到新创建的PyStringObject中

  Memcpy(op->ob_sval, a->ob_sval , a->ob_size) ;

  Memcpy(op->ob_sval+a->ob_size , b->ob_sval , b->ob_size) ;

  Op->ob_sval[size] = ‘\0’;

  Return (PyObject*)op ;

  # undif b ;

}

 

 

 

Static PyObject * string_join(PyStringObject *self,PyObject *orig)

{

   Char *sep = PyString_AS_STRING(self) ;

   Const Py_ssize_t seplen = PyString_GET_SIZE(self) ;

   PyObject *res = NULL ;

   Char *p ;

   Py_ssize_t seqlen = 0 ;

   Size_t sz=0 ;

   Py_ssize_t i ;

   PyObject *seq, *item;

   Seq = PySequence_Fast(orig, “”);

   If( seq == NULL )

   {

       Return NULL ;

}

Seqlen = PySequence_Size(seq) ;

If( seqlen == 0 )

{

    Py_DECREF(seq) ;

    Return PyString_FromString(“”);

}

If( seqlen == 1)

{

   Item = PySequence_Fast_ITEM(seq,0) ;

   If( PyString_CheckExact(item)||PyUnicode_CheckExact(item))

   {

       Py_INCREF(item) ;

       Py_DECREF(seq) ;

       Return item ;

   }

}

 

For( i = 0 ; i < seqlen ; i++)

{

    Const size_t old_sz = sz ;

    Item = PySequence_Fast_GET_ITEM(seq,i) ;

    If( ! PyString_Check(item))

    {

        PyErr_Format(PyExc_TypeError,“sequence item %zd:expected string,”) ;

        Py_DECREF(seq) ;

        Return NULL ;

     }

     Sz += PyString_GET_SIZE(item) ;

     If( I != 0 )

        Sz += seqlen ;

     Res = PyString_FromStringAndSize((char*)NULL , sz) ;

     If( res == NULL)

     {

         Py_DECREF(seq) ;

         Return NULL ;

      }

      P = PyString_AS_STRING(res) ;

      For( I = 0 ; I < seqlen; ++ i)

      {

           Size_t n ;

           Item = PySeqence_Fast_GET_ITEM(seq, i) ;

           n = PyString_GET_SIZE(item);

           Py_MEMCPY(p ,PyString_AS_STRING(item) , n) ;

           P+=n ;

           If( I < seqlen-1)

           {

              Py_MEMCPY(p,seq,seplen) ;

              P+=sepen ;

           }

       }

       Py_DECREF(seq) ;

       Return res;

  }

   

   

转载于:https://www.cnblogs.com/liuze/archive/2010/06/04/1751375.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值