Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(80)

Unified Diff: Objects/rangeobject.c

Issue 602: range: lean and mean (Closed) SVN Base: http://svn.python.org/view/*checkout*/python/branches/py3k/
Patch Set: Created 5 months, 2 weeks ago , Downloaded from: http://bugs.python.org/file10152/range_lean_and_mean.patch
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View side by-side-diff with in-line comments
Download patch
Index: Objects/rangeobject.c
===================================================================
--- Objects/rangeobject.c (revision 62616)
+++ Objects/rangeobject.c (working copy)
@@ -14,6 +14,7 @@
PyObject *start;
PyObject *stop;
PyObject *step;
+ PyObject *length;
mvloewis 2008/05/02 05:43:57 What is the purpose of caching the length in the r
GvR 2008/05/02 13:52:47 On 2008/05/02 05:43:57, mvloewis wrote: > What is
Benjamin 2008/05/02 16:56:18 On 2008/05/02 05:43:57, mvloewis wrote: > What is
} rangeobject;
/* Helper function for validating step. Always returns a new reference or
@@ -43,6 +44,9 @@
return step;
}
+static PyObject* range_compute_length(PyObject *start,
+ PyObject *stop, PyObject *step);
GvR 2008/05/02 13:52:47 This line is indented one space too many.
+
/* XXX(nnorwitz): should we error check if the user passes any empty ranges?
range(-10)
range(0, -5)
@@ -52,7 +56,7 @@
range_new(PyTypeObject *type, PyObject *args, PyObject *kw)
{
rangeobject *obj = NULL;
- PyObject *start = NULL, *stop = NULL, *step = NULL;
+ PyObject *start = NULL, *stop = NULL, *step = NULL, *length = NULL;
if (!_PyArg_NoKeywords("range()", kw))
return NULL;
@@ -81,25 +85,30 @@
goto Fail;
}
+ length = range_compute_length(start, stop, step);
+ if (length == NULL)
+ goto Fail;
obj = PyObject_New(rangeobject, &PyRange_Type);
if (obj == NULL)
goto Fail;
obj->start = start;
obj->stop = stop;
obj->step = step;
+ obj->length = length;
return (PyObject *) obj;
Fail:
Py_XDECREF(start);
Py_XDECREF(stop);
Py_XDECREF(step);
+ Py_XDECREF(length);
return NULL;
}
PyDoc_STRVAR(range_doc,
"range([start,] stop[, step]) -> range object\n\
\n\
-Returns an iterator that generates the numbers in the range on demand.");
+Returns a virtual sequence of numbers from start to stop by step.");
GvR 2008/05/02 13:52:47 I really don't want to use the word sequence here.
static void
range_dealloc(rangeobject *r)
@@ -107,6 +116,7 @@
Py_DECREF(r->start);
Py_DECREF(r->stop);
Py_DECREF(r->step);
+ Py_DECREF(r->length);
PyObject_Del(r);
}
@@ -116,8 +126,8 @@
* Arguments MUST return 1 with either PyLong_Check() or
* PyLong_Check(). Return -1 when there is an error.
GvR 2008/05/02 13:52:47 Not your fault, but this comment still references
*/
-static PyObject*
-range_length_obj(rangeobject *r)
+static PyObject *
+range_compute_length(PyObject *start, PyObject *stop, PyObject *step)
{
/* -------------------------------------------------------------
Algorithm is equal to that of get_len_of_range(), but it operates
@@ -125,7 +135,6 @@
---------------------------------------------------------------*/
int cmp_result, cmp_call;
PyObject *lo, *hi;
- PyObject *step = NULL;
PyObject *diff = NULL;
PyObject *one = NULL;
PyObject *tmp1 = NULL, *tmp2 = NULL, *result;
@@ -134,23 +143,22 @@
PyObject *zero = PyLong_FromLong(0);
if (zero == NULL)
return NULL;
- cmp_call = PyObject_Cmp(r->step, zero, &cmp_result);
+ cmp_call = PyObject_Cmp(step, zero, &cmp_result);
Py_DECREF(zero);
if (cmp_call == -1)
return NULL;
assert(cmp_result != 0);
if (cmp_result > 0) {
- lo = r->start;
- hi = r->stop;
- step = r->step;
+ lo = start;
+ hi = stop;
Py_INCREF(step);
} else {
- lo = r->stop;
- hi = r->start;
- step = PyNumber_Negative(r->step);
+ lo = stop;
+ hi = start;
+ step = PyNumber_Negative(step);
if (!step)
- return NULL;
+ goto Fail;
}
/* if (lo >= hi), return length of 0. */
@@ -193,46 +201,11 @@
static Py_ssize_t
range_length(rangeobject *r)
{
- PyObject *len = range_length_obj(r);
- Py_ssize_t result = -1;
- if (len) {
- result = PyLong_AsSsize_t(len);
- Py_DECREF(len);
- }
- return result;
+ return PyLong_AsSsize_t(r->length);
}
-/* range(...)[x] is necessary for: seq[:] = range(...) */
static PyObject *
-range_item(rangeobject *r, Py_ssize_t i)
-{
- Py_ssize_t len = range_length(r);
- PyObject *rem, *incr, *result;
-
- /* XXX(nnorwitz): should negative indices be supported? */
- /* XXX(nnorwitz): should support range[x] where x > PY_SSIZE_T_MAX? */
- if (i < 0 || i >= len) {
- if (!PyErr_Occurred())
- PyErr_SetString(PyExc_IndexError,
- "range object index out of range");
- return NULL;
- }
-
- /* XXX(nnorwitz): optimize for short ints. */
- rem = PyLong_FromSsize_t(i);
- if (!rem)
- return NULL;
- incr = PyNumber_Multiply(rem, r->step);
- Py_DECREF(rem);
- if (!incr)
- return NULL;
- result = PyNumber_Add(r->start, incr);
- Py_DECREF(incr);
- return result;
-}
-
-static PyObject *
range_repr(rangeobject *r)
{
Py_ssize_t istep;
@@ -252,12 +225,40 @@
r->start, r->stop, r->step);
}
+static PyObject *
+range_getstart(rangeobject *obj)
+{
+ return obj->start;
+}
+
+static PyObject *
+range_getstop(rangeobject *obj)
+{
+ return obj->stop;
+}
+
+static PyObject *
+range_getstep(rangeobject *obj)
+{
+ return obj->step;
+}
+
+static PyGetSetDef range_getset[] = {
+ {"start", (getter)range_getstart, NULL, "The start of the range"},
+ {"stop", (getter)range_getstop, NULL, "Where the range stops."},
+ {"step", (getter)range_getstep, NULL, "How much the range jumps."},
+ {0},
+};
+
static PySequenceMethods range_as_sequence = {
(lenfunc)range_length, /* sq_length */
GvR 2008/05/02 13:52:47 The latest discussion on the list suggests to remo
- 0, /* sq_concat */
- 0, /* sq_repeat */
- (ssizeargfunc)range_item, /* sq_item */
- 0, /* sq_slice */
+ 0, /* sq_concat */
+ 0, /* sq_repeat */
+ 0, /* sq_item */
+ 0, /* sq_slice */
+ 0, /* sq_ass_item */
+ 0, /* sq_ass_slice */
+ 0, /* sq_contains */
};
static PyObject * range_iter(PyObject *seq);
@@ -285,7 +286,7 @@
(reprfunc)range_repr, /* tp_repr */
0, /* tp_as_number */
&range_as_sequence, /* tp_as_sequence */
- 0, /* tp_as_mapping */
+ 0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
@@ -302,7 +303,7 @@
0, /* tp_iternext */
range_methods, /* tp_methods */
0, /* tp_members */
- 0, /* tp_getset */
+ range_getset, /* tp_getset */
GvR 2008/05/02 13:52:47 Please use spaces to indent the comment.
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
@@ -647,9 +648,7 @@
return NULL;
/* start + (len - 1) * step */
- len = range_length_obj(range);
- if (!len)
- goto create_failure;
+ len = range->length;
one = PyLong_FromLong(1);
if (!one)
« Lib/test/test_range.py ('k') | no next file »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld r338