SF feature request #686323: Minor array module enhancements

array.extend() now accepts iterable arguments implements as a series
of appends.  Besides being a user convenience and matching the behavior
for lists, this the saves memory and cycles that would be used to
create a temporary array object.
This commit is contained in:
Raymond Hettinger 2004-03-14 05:43:59 +00:00
parent 6e2ee866fa
commit 49f9bd15ff
4 changed files with 51 additions and 14 deletions

View file

@ -104,10 +104,13 @@ data from a file written on a machine with a different byte order.
Return the number of occurences of \var{x} in the array. Return the number of occurences of \var{x} in the array.
\end{methoddesc} \end{methoddesc}
\begin{methoddesc}[array]{extend}{a} \begin{methoddesc}[array]{extend}{iterable}
Append array items from \var{a} to the end of the array. The two Append items from \var{iterable} to the end of the array. If
arrays must have \emph{exactly} the same type code; if not, \var{iterable} is another array, it must have \emph{exactly} the same
\exception{TypeError} will be raised. type code; if not, \exception{TypeError} will be raised. If
\var{iterable} is not an array, it must be iterable and its
elements must be the right type to be appended to the array.
\versionchanged[Formerly, the argument could only be another array]{2.4}
\end{methoddesc} \end{methoddesc}
\begin{methoddesc}[array]{fromfile}{f, n} \begin{methoddesc}[array]{fromfile}{f, n}

View file

@ -592,6 +592,13 @@ class BaseTest(unittest.TestCase):
b = array.array(self.badtypecode()) b = array.array(self.badtypecode())
self.assertRaises(TypeError, a.extend, b) self.assertRaises(TypeError, a.extend, b)
a = array.array(self.typecode, self.example)
a.extend(self.example[::-1])
self.assertEqual(
a,
array.array(self.typecode, self.example+self.example[::-1])
)
def test_coveritertraverse(self): def test_coveritertraverse(self):
try: try:
import gc import gc

View file

@ -182,7 +182,9 @@ Extension modules
- array objects now support the copy module. Also, their resizing - array objects now support the copy module. Also, their resizing
scheme has been updated the same as for list objects. The improves scheme has been updated the same as for list objects. The improves
performance for append() operations. the performance (speed and memory usage) of append() operations.
Also, array.extend() now accepts any iterable argument for repeated
appends without needing to create another temporary array.
- cStringIO.writelines() now accepts any iterable argument and writes - cStringIO.writelines() now accepts any iterable argument and writes
the lines one at a time rather than joining them and writing once. the lines one at a time rather than joining them and writing once.

View file

@ -774,17 +774,36 @@ setarrayitem(PyObject *a, int i, PyObject *v)
return array_ass_item((arrayobject *)a, i, v); return array_ass_item((arrayobject *)a, i, v);
} }
static int
array_iter_extend(arrayobject *self, PyObject *bb)
{
PyObject *it, *v;
it = PyObject_GetIter(bb);
if (it == NULL)
return -1;
while ((v = PyIter_Next(it)) != NULL) {
if (ins1(self, (int) self->ob_size, v) != 0) {
Py_DECREF(v);
Py_DECREF(it);
return -1;
}
Py_DECREF(v);
}
Py_DECREF(it);
if (PyErr_Occurred())
return -1;
return 0;
}
static int static int
array_do_extend(arrayobject *self, PyObject *bb) array_do_extend(arrayobject *self, PyObject *bb)
{ {
int size; int size;
if (!array_Check(bb)) { if (!array_Check(bb))
PyErr_Format(PyExc_TypeError, return array_iter_extend(self, bb);
"can only extend array with array (not \"%.200s\")",
bb->ob_type->tp_name);
return -1;
}
#define b ((arrayobject *)bb) #define b ((arrayobject *)bb)
if (self->ob_descr != b->ob_descr) { if (self->ob_descr != b->ob_descr) {
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
@ -810,6 +829,12 @@ array_do_extend(arrayobject *self, PyObject *bb)
static PyObject * static PyObject *
array_inplace_concat(arrayobject *self, PyObject *bb) array_inplace_concat(arrayobject *self, PyObject *bb)
{ {
if (!array_Check(bb)) {
PyErr_Format(PyExc_TypeError,
"can only extend array with array (not \"%.200s\")",
bb->ob_type->tp_name);
return NULL;
}
if (array_do_extend(self, bb) == -1) if (array_do_extend(self, bb) == -1)
return NULL; return NULL;
Py_INCREF(self); Py_INCREF(self);
@ -990,9 +1015,9 @@ array_extend(arrayobject *self, PyObject *bb)
} }
PyDoc_STRVAR(extend_doc, PyDoc_STRVAR(extend_doc,
"extend(array)\n\ "extend(array or iterable)\n\
\n\ \n\
Append array items to the end of the array."); Append items to the end of the array.");
static PyObject * static PyObject *
array_insert(arrayobject *self, PyObject *args) array_insert(arrayobject *self, PyObject *args)
@ -1881,7 +1906,7 @@ append() -- append a new item to the end of the array\n\
buffer_info() -- return information giving the current memory info\n\ buffer_info() -- return information giving the current memory info\n\
byteswap() -- byteswap all the items of the array\n\ byteswap() -- byteswap all the items of the array\n\
count() -- return number of occurences of an object\n\ count() -- return number of occurences of an object\n\
extend() -- extend array by appending array elements\n\ extend() -- extend array by appending multiple elements from an iterable\n\
fromfile() -- read items from a file object\n\ fromfile() -- read items from a file object\n\
fromlist() -- append items from the list\n\ fromlist() -- append items from the list\n\
fromstring() -- append items from the string\n\ fromstring() -- append items from the string\n\