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;

  }

   

   

posted on 2010-06-04 13:54  liuze  阅读(368)  评论(0编辑  收藏  举报