Rip out the fancy behaviors of xrange that nobody uses: repeat, slice,

contains, tolist(), and the start/stop/step attributes.  This includes
removing the 4th ('repeat') argument to PyRange_New().
This commit is contained in:
Guido van Rossum 2001-07-05 13:27:48 +00:00
parent 25ddc6330f
commit 3f56166b1a
3 changed files with 18 additions and 229 deletions

View File

@ -775,12 +775,8 @@ xrange object will always take the same amount of memory, no matter the
size of the range it represents. There are no consistent performance
advantages.
XRange objects behave like tuples, and offer a single method:
\begin{methoddesc}[xrange]{tolist}{}
Return a list object which represents the same values as the xrange
object.
\end{methoddesc}
XRange objects have very little behavior: they only support indexing
and the \function{len()} function.
\subsubsection{Mutable Sequence Types \label{typesseq-mutable}}

View File

@ -19,7 +19,7 @@ extern DL_IMPORT(PyTypeObject) PyRange_Type;
#define PyRange_Check(op) ((op)->ob_type == &PyRange_Type)
extern DL_IMPORT(PyObject *) PyRange_New(long, long, long, int);
extern DL_IMPORT(PyObject *) PyRange_New(long, long, long);
#ifdef __cplusplus
}

View File

@ -10,58 +10,20 @@ typedef struct {
long start;
long step;
long len;
int reps;
long totlen;
} rangeobject;
static int
long_mul(long i, long j, long *kk)
{
PyObject *a;
PyObject *b;
PyObject *c;
if ((a = PyInt_FromLong(i)) == NULL)
return 0;
if ((b = PyInt_FromLong(j)) == NULL)
return 0;
c = PyNumber_Multiply(a, b);
Py_DECREF(a);
Py_DECREF(b);
if (c == NULL)
return 0;
*kk = PyInt_AS_LONG(c);
Py_DECREF(c);
if (*kk > INT_MAX) {
PyErr_SetString(PyExc_OverflowError,
"integer multiplication");
return 0;
}
else
return 1;
}
PyObject *
PyRange_New(long start, long len, long step, int reps)
PyRange_New(long start, long len, long step)
{
long totlen = -1;
rangeobject *obj = PyObject_NEW(rangeobject, &PyRange_Type);
if (obj == NULL)
return NULL;
if (len == 0 || reps <= 0) {
if (len == 0) {
start = 0;
len = 0;
step = 1;
reps = 1;
totlen = 0;
}
else {
long last = start + (len - 1) * step;
@ -71,20 +33,12 @@ PyRange_New(long start, long len, long step, int reps)
PyErr_SetString(PyExc_OverflowError,
"integer addition");
return NULL;
}
if (! long_mul(len, (long) reps, &totlen)) {
if(!PyErr_ExceptionMatches(PyExc_OverflowError))
return NULL;
PyErr_Clear();
totlen = -1;
}
}
obj->start = start;
obj->len = len;
obj->step = step;
obj->reps = reps;
obj->totlen = totlen;
return (PyObject *) obj;
}
@ -98,12 +52,11 @@ range_dealloc(rangeobject *r)
static PyObject *
range_item(rangeobject *r, int i)
{
if (i < 0 || i >= r->totlen)
if (r->totlen!=-1) {
PyErr_SetString(PyExc_IndexError,
if (i < 0 || i >= r->len) {
PyErr_SetString(PyExc_IndexError,
"xrange object index out of range");
return NULL;
}
return NULL;
}
return PyInt_FromLong(r->start + (i % r->len) * r->step);
}
@ -111,10 +64,7 @@ range_item(rangeobject *r, int i)
static int
range_length(rangeobject *r)
{
if (r->totlen == -1)
PyErr_SetString(PyExc_OverflowError,
"xrange object has too many items");
return r->totlen;
return r->len;
}
static PyObject *
@ -124,7 +74,6 @@ range_repr(rangeobject *r)
* a bit of "(xrange(...) * ...)" text.
*/
char buf1[250];
char buf2[250];
if (r->start == 0 && r->step == 1)
sprintf(buf1, "xrange(%ld)", r->start + r->len * r->step);
@ -140,174 +89,18 @@ range_repr(rangeobject *r)
r->start + r->len * r->step,
r->step);
if (r->reps != 1)
sprintf(buf2, "(%s * %d)", buf1, r->reps);
return PyString_FromString(r->reps == 1 ? buf1 : buf2);
}
static PyObject *
range_concat(rangeobject *r, PyObject *obj)
{
PyErr_SetString(PyExc_TypeError, "cannot concatenate xrange objects");
return NULL;
}
static PyObject *
range_repeat(rangeobject *r, int n)
{
long lreps = 0;
if (n <= 0)
return (PyObject *) PyRange_New(0, 0, 1, 1);
else if (n == 1) {
Py_INCREF(r);
return (PyObject *) r;
}
else if (! long_mul((long) r->reps, (long) n, &lreps))
return NULL;
else
return (PyObject *) PyRange_New(
r->start,
r->len,
r->step,
(int) lreps);
}
static int
range_compare(rangeobject *r1, rangeobject *r2)
{
if (r1->start != r2->start)
return r1->start - r2->start;
else if (r1->step != r2->step)
return r1->step - r2->step;
else if (r1->len != r2->len)
return r1->len - r2->len;
else
return r1->reps - r2->reps;
}
static PyObject *
range_slice(rangeobject *r, int low, int high)
{
if (r->reps != 1) {
PyErr_SetString(PyExc_TypeError,
"cannot slice a replicated xrange");
return NULL;
}
if (low < 0)
low = 0;
else if (low > r->len)
low = r->len;
if (high < 0)
high = 0;
if (high < low)
high = low;
else if (high > r->len)
high = r->len;
if (low == 0 && high == r->len) {
Py_INCREF(r);
return (PyObject *) r;
}
return (PyObject *) PyRange_New(
low * r->step + r->start,
high - low,
r->step,
1);
}
static PyObject *
range_tolist(rangeobject *self, PyObject *args)
{
PyObject *thelist;
int j;
if (! PyArg_ParseTuple(args, ":tolist"))
return NULL;
if (self->totlen == -1)
return PyErr_NoMemory();
if ((thelist = PyList_New(self->totlen)) == NULL)
return NULL;
for (j = 0; j < self->totlen; ++j)
if ((PyList_SetItem(thelist, j, (PyObject *) PyInt_FromLong(
self->start + (j % self->len) * self->step))) < 0)
return NULL;
return thelist;
}
static PyObject *
range_getattr(rangeobject *r, char *name)
{
PyObject *result;
static PyMethodDef range_methods[] = {
{"tolist", (PyCFunction)range_tolist, METH_VARARGS,
"tolist() -> list\n"
"Return a list object with the same values."},
{NULL, NULL}
};
static struct memberlist range_members[] = {
{"step", T_LONG, offsetof(rangeobject, step), RO},
{"start", T_LONG, offsetof(rangeobject, start), RO},
{"stop", T_LONG, 0, RO},
{NULL, 0, 0, 0}
};
result = Py_FindMethod(range_methods, (PyObject *) r, name);
if (result == NULL) {
PyErr_Clear();
if (strcmp("stop", name) == 0)
result = PyInt_FromLong(r->start + (r->len * r->step));
else
result = PyMember_Get((char *)r, range_members, name);
}
return result;
}
static int
range_contains(rangeobject *r, PyObject *obj)
{
long num = PyInt_AsLong(obj);
if (num < 0 && PyErr_Occurred())
return -1;
if (r->step > 0) {
if ((num < r->start) || ((num - r->start) % r->step))
return 0;
if (num >= (r->start + (r->len * r->step)))
return 0;
}
else {
if ((num > r->start) || ((num - r->start) % r->step))
return 0;
if (num <= (r->start + (r->len * r->step)))
return 0;
}
return 1;
return PyString_FromString(buf1);
}
static PySequenceMethods range_as_sequence = {
(inquiry)range_length, /*sq_length*/
(binaryfunc)range_concat, /*sq_concat*/
(intargfunc)range_repeat, /*sq_repeat*/
(intargfunc)range_item, /*sq_item*/
(intintargfunc)range_slice, /*sq_slice*/
0, /*sq_concat*/
0, /*sq_repeat*/
(intargfunc)range_item, /*sq_item*/
0, /*sq_slice*/
0, /*sq_ass_item*/
0, /*sq_ass_slice*/
(objobjproc)range_contains, /*sq_contains*/
0, /*sq_contains*/
};
PyTypeObject PyRange_Type = {
@ -318,9 +111,9 @@ PyTypeObject PyRange_Type = {
0, /* Item size for varobject */
(destructor)range_dealloc, /*tp_dealloc*/
0, /*tp_print*/
(getattrfunc)range_getattr, /*tp_getattr*/
0, /*tp_getattr*/
0, /*tp_setattr*/
(cmpfunc)range_compare, /*tp_compare*/
0, /*tp_compare*/
(reprfunc)range_repr, /*tp_repr*/
0, /*tp_as_number*/
&range_as_sequence, /*tp_as_sequence*/