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

Delta Between Two Patch Sets: Objects/rangeobject.c

Issue 602: range: lean and mean (Closed) SVN Base: http://svn.python.org/view/*checkout*/python/branches/py3k/
Left Patch Set: Created 3 months, 4 weeks ago , Downloaded from: http://bugs.python.org/file10152/range_lean_and_mean.patch
Right Patch Set: in response to reviews Created 3 months, 3 weeks ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
LEFTRIGHT
1 /* Range object implementation */ 1 /* Range object implementation */
2 2
3 #include "Python.h" 3 #include "Python.h"
4 #include "structmember.h"
4 5
5 /* Support objects whose length is > PY_SSIZE_T_MAX. 6 /* Support objects whose length is > PY_SSIZE_T_MAX.
6 7
7 This could be sped up for small PyLongs if they fit in an Py_ssize_t. 8 This could be sped up for small PyLongs if they fit in an Py_ssize_t.
8 This only matters on Win64. Though we could use PY_LONG_LONG which 9 This only matters on Win64. Though we could use PY_LONG_LONG which
9 would presumably help perf. 10 would presumably help perf.
10 */ 11 */
11 12
12 typedef struct { 13 typedef struct {
13 PyObject_HEAD 14 PyObject_HEAD
14 PyObject *start; 15 PyObject *start;
15 PyObject *stop; 16 PyObject *stop;
16 PyObject *step; 17 PyObject *step;
17 PyObject *length; 18 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
18 } rangeobject; 19 } rangeobject;
19 20
20 /* Helper function for validating step. Always returns a new reference or 21 /* Helper function for validating step. Always returns a new reference or
21 NULL on error. 22 NULL on error.
22 */ 23 */
23 static PyObject * 24 static PyObject *
24 validate_step(PyObject *step) 25 validate_step(PyObject *step)
25 { 26 {
26 /* No step specified, use a step of 1. */ 27 /* No step specified, use a step of 1. */
27 if (!step) 28 if (!step)
28 return PyLong_FromLong(1); 29 return PyLong_FromLong(1);
29 30
30 step = PyNumber_Index(step); 31 step = PyNumber_Index(step);
31 if (step) { 32 if (step) {
32 Py_ssize_t istep = PyNumber_AsSsize_t(step, NULL); 33 Py_ssize_t istep = PyNumber_AsSsize_t(step, NULL);
33 if (istep == -1 && PyErr_Occurred()) { 34 if (istep == -1 && PyErr_Occurred()) {
34 /* Ignore OverflowError, we know the value isn't 0. */ 35 /* Ignore OverflowError, we know the value isn't 0. */
35 PyErr_Clear(); 36 PyErr_Clear();
36 } 37 }
37 else if (istep == 0) { 38 else if (istep == 0) {
38 PyErr_SetString(PyExc_ValueError, 39 PyErr_SetString(PyExc_ValueError,
39 "range() arg 3 must not be zero"); 40 "range() arg 3 must not be zero");
40 Py_CLEAR(step); 41 Py_CLEAR(step);
41 } 42 }
42 } 43 }
43 44
44 return step; 45 return step;
45 } 46 }
46 47
47 static PyObject* range_compute_length(PyObject *start, 48 static PyObject* range_compute_length(PyObject *start,
48 PyObject *stop, PyObject *step); 49 PyObject *stop, PyObject *step);
GvR 2008/05/02 13:52:47 This line is indented one space too many.
49 50
50 /* XXX(nnorwitz): should we error check if the user passes any empty ranges? 51 /* XXX(nnorwitz): should we error check if the user passes any empty ranges?
51 range(-10) 52 range(-10)
52 range(0, -5) 53 range(0, -5)
53 range(0, 5, -1) 54 range(0, 5, -1)
54 */ 55 */
55 static PyObject * 56 static PyObject *
56 range_new(PyTypeObject *type, PyObject *args, PyObject *kw) 57 range_new(PyTypeObject *type, PyObject *args, PyObject *kw)
57 { 58 {
58 rangeobject *obj = NULL; 59 rangeobject *obj = NULL;
59 PyObject *start = NULL, *stop = NULL, *step = NULL, *length = NULL; 60 PyObject *start = NULL, *stop = NULL, *step = NULL, *length = NULL;
60 61
61 if (!_PyArg_NoKeywords("range()", kw)) 62 if (!_PyArg_NoKeywords("range()", kw))
62 return NULL; 63 return NULL;
63 64
64 if (PyTuple_Size(args) <= 1) { 65 if (PyTuple_Size(args) <= 1) {
65 if (!PyArg_UnpackTuple(args, "range", 1, 1, &stop)) 66 if (!PyArg_UnpackTuple(args, "range", 1, 1, &stop))
66 goto Fail; 67 goto Fail;
67 stop = PyNumber_Index(stop); 68 stop = PyNumber_Index(stop);
68 if (!stop) 69 if (!stop)
69 goto Fail; 70 goto Fail;
70 start = PyLong_FromLong(0); 71 start = PyLong_FromLong(0);
71 step = PyLong_FromLong(1); 72 step = PyLong_FromLong(1);
72 if (!start || !step) 73 if (!start || !step)
73 goto Fail; 74 goto Fail;
74 } 75 }
75 else { 76 else {
76 if (!PyArg_UnpackTuple(args, "range", 2, 3, 77 if (!PyArg_UnpackTuple(args, "range", 2, 3,
77 &start, &stop, &step)) 78 &start, &stop, &step))
78 goto Fail; 79 goto Fail;
79 80
80 /* Convert borrowed refs to owned refs */ 81 /* Convert borrowed refs to owned refs */
81 start = PyNumber_Index(start); 82 start = PyNumber_Index(start);
82 stop = PyNumber_Index(stop); 83 stop = PyNumber_Index(stop);
83 step = validate_step(step); 84 step = validate_step(step);
84 if (!start || !stop || !step) 85 if (!start || !stop || !step)
85 goto Fail; 86 goto Fail;
86 } 87 }
87 88
88 length = range_compute_length(start, stop, step); 89 length = range_compute_length(start, stop, step);
89 if (length == NULL) 90 if (length == NULL)
90 goto Fail; 91 goto Fail;
91 obj = PyObject_New(rangeobject, &PyRange_Type); 92 obj = PyObject_New(rangeobject, &PyRange_Type);
92 if (obj == NULL) 93 if (obj == NULL)
93 goto Fail; 94 goto Fail;
94 obj->start = start; 95 obj->start = start;
95 obj->stop = stop; 96 obj->stop = stop;
96 obj->step = step; 97 obj->step = step;
97 obj->length = length; 98 obj->length = length;
98 return (PyObject *) obj; 99 return (PyObject *) obj;
99 100
100 Fail: 101 Fail:
101 Py_XDECREF(start); 102 Py_XDECREF(start);
102 Py_XDECREF(stop); 103 Py_XDECREF(stop);
103 Py_XDECREF(step); 104 Py_XDECREF(step);
104 Py_XDECREF(length); 105 Py_XDECREF(length);
105 return NULL; 106 return NULL;
106 } 107 }
107 108
108 PyDoc_STRVAR(range_doc, 109 PyDoc_STRVAR(range_doc,
109 "range([start,] stop[, step]) -> range object\n\ 110 "range([start,] stop[, step]) -> range object\n\
110 \n\ 111 \n\
111 Returns a virtual sequence of numbers from start to stop by step."); 112 Return an arithmetic progression of numbers from start "
GvR 2008/05/02 13:52:47 I really don't want to use the word sequence here.
113 "to stop (exclusive) by step.");
112 114
113 static void 115 static void
114 range_dealloc(rangeobject *r) 116 range_dealloc(rangeobject *r)
115 { 117 {
116 Py_DECREF(r->start); 118 Py_DECREF(r->start);
117 Py_DECREF(r->stop); 119 Py_DECREF(r->stop);
118 Py_DECREF(r->step); 120 Py_DECREF(r->step);
119 Py_DECREF(r->length); 121 Py_DECREF(r->length);
120 PyObject_Del(r); 122 PyObject_Del(r);
121 } 123 }
122 124
GvR 2008/05/03 05:04:35 Hm. I didn't mean for you to delete the entire com
123 /* Return number of items in range (lo, hi, step), when arguments are
124 * PyInt or PyLong objects. step > 0 required. Return a value < 0 if
125 * & only if the true value is too large to fit in a signed long.
126 * Arguments MUST return 1 with either PyLong_Check() or
127 * PyLong_Check(). Return -1 when there is an error.
GvR 2008/05/02 13:52:47 Not your fault, but this comment still references
128 */
129 static PyObject * 125 static PyObject *
130 range_compute_length(PyObject *start, PyObject *stop, PyObject *step) 126 range_compute_length(PyObject *start, PyObject *stop, PyObject *step)
131 { 127 {
132 /* ------------------------------------------------------------- 128 /* -------------------------------------------------------------
133 Algorithm is equal to that of get_len_of_range(), but it operates 129 Algorithm is equal to that of get_len_of_range(), but it operates
134 on PyObjects (which are assumed to be PyLong or PyInt objects). 130 on PyObjects (which are assumed to be PyLong or PyInt objects).
135 ---------------------------------------------------------------*/ 131 ---------------------------------------------------------------*/
136 int cmp_result, cmp_call; 132 int cmp_result, cmp_call;
137 PyObject *lo, *hi; 133 PyObject *lo, *hi;
138 PyObject *diff = NULL; 134 PyObject *diff = NULL;
139 PyObject *one = NULL; 135 PyObject *one = NULL;
140 PyObject *tmp1 = NULL, *tmp2 = NULL, *result; 136 PyObject *tmp1 = NULL, *tmp2 = NULL, *result;
141 /* holds sub-expression evaluations */ 137 /* holds sub-expression evaluations */
142 138
143 PyObject *zero = PyLong_FromLong(0); 139 PyObject *zero = PyLong_FromLong(0);
144 if (zero == NULL) 140 if (zero == NULL)
145 return NULL; 141 return NULL;
146 cmp_call = PyObject_Cmp(step, zero, &cmp_result); 142 cmp_call = PyObject_Cmp(step, zero, &cmp_result);
147 Py_DECREF(zero); 143 Py_DECREF(zero);
148 if (cmp_call == -1) 144 if (cmp_call == -1)
149 return NULL; 145 return NULL;
150 146
151 assert(cmp_result != 0); 147 assert(cmp_result != 0);
152 if (cmp_result > 0) { 148 if (cmp_result > 0) {
153 lo = start; 149 lo = start;
154 hi = stop; 150 hi = stop;
155 Py_INCREF(step); 151 Py_INCREF(step);
156 } else { 152 } else {
157 lo = stop; 153 lo = stop;
158 hi = start; 154 hi = start;
159 step = PyNumber_Negative(step); 155 step = PyNumber_Negative(step);
160 if (!step) 156 if (!step)
161 goto Fail; 157 goto Fail;
162 } 158 }
163 159
164 /* if (lo >= hi), return length of 0. */ 160 /* if (lo >= hi), return length of 0. */
165 if (PyObject_Compare(lo, hi) >= 0) { 161 if (PyObject_Compare(lo, hi) >= 0) {
166 Py_XDECREF(step); 162 Py_XDECREF(step);
167 return PyLong_FromLong(0); 163 return PyLong_FromLong(0);
168 } 164 }
169 165
170 if ((one = PyLong_FromLong(1L)) == NULL) 166 if ((one = PyLong_FromLong(1L)) == NULL)
171 goto Fail; 167 goto Fail;
172 168
173 if ((tmp1 = PyNumber_Subtract(hi, lo)) == NULL) 169 if ((tmp1 = PyNumber_Subtract(hi, lo)) == NULL)
174 goto Fail; 170 goto Fail;
175 171
176 if ((diff = PyNumber_Subtract(tmp1, one)) == NULL) 172 if ((diff = PyNumber_Subtract(tmp1, one)) == NULL)
177 goto Fail; 173 goto Fail;
178 174
179 if ((tmp2 = PyNumber_FloorDivide(diff, step)) == NULL) 175 if ((tmp2 = PyNumber_FloorDivide(diff, step)) == NULL)
180 goto Fail; 176 goto Fail;
181 177
182 if ((result = PyNumber_Add(tmp2, one)) == NULL) 178 if ((result = PyNumber_Add(tmp2, one)) == NULL)
183 goto Fail; 179 goto Fail;
184 180
185 Py_DECREF(tmp2); 181 Py_DECREF(tmp2);
186 Py_DECREF(diff); 182 Py_DECREF(diff);
187 Py_DECREF(step); 183 Py_DECREF(step);
188 Py_DECREF(tmp1); 184 Py_DECREF(tmp1);
189 Py_DECREF(one); 185 Py_DECREF(one);
190 return result; 186 return result;
191 187
192 Fail: 188 Fail:
193 Py_XDECREF(tmp2); 189 Py_XDECREF(tmp2);
194 Py_XDECREF(diff); 190 Py_XDECREF(diff);
195 Py_XDECREF(step); 191 Py_XDECREF(step);
196 Py_XDECREF(tmp1); 192 Py_XDECREF(tmp1);
197 Py_XDECREF(one); 193 Py_XDECREF(one);
198 return NULL; 194 return NULL;
199 } 195 }
200 196
201 static Py_ssize_t 197 static PyObject *
202 range_length(rangeobject *r) 198 range_length_hint(rangeobject *r)
203 { 199 {
204 return PyLong_AsSsize_t(r->length); 200 Py_INCREF(r->length);
205 } 201 return r->length;
202 }
203
204 PyDoc_STRVAR(range_length_hint_doc,
205 "__length_hint__() -> int\n"
206 "Return a estimate of len(list(range)).");
206 207
207 208
208 static PyObject * 209 static PyObject *
209 range_repr(rangeobject *r) 210 range_repr(rangeobject *r)
210 { 211 {
211 Py_ssize_t istep; 212 Py_ssize_t istep;
212 213
213 /* Check for special case values for printing. We don't always 214 /* Check for special case values for printing. We don't always
214 need the step value. We don't care about errors 215 need the step value. We don't care about errors
215 (it means overflow), so clear the errors. */ 216 (it means overflow), so clear the errors. */
216 istep = PyNumber_AsSsize_t(r->step, NULL); 217 istep = PyNumber_AsSsize_t(r->step, NULL);
217 if (istep != 1 || (istep == -1 && PyErr_Occurred())) { 218 if (istep != 1 || (istep == -1 && PyErr_Occurred())) {
218 PyErr_Clear(); 219 PyErr_Clear();
219 } 220 }
220 221
221 if (istep == 1) 222 if (istep == 1)
222 return PyUnicode_FromFormat("range(%R, %R)", r->start, r->stop); 223 return PyUnicode_FromFormat("range(%R, %R)", r->start, r->stop);
223 else 224 else
224 return PyUnicode_FromFormat("range(%R, %R, %R)", 225 return PyUnicode_FromFormat("range(%R, %R, %R)",
225 r->start, r->stop, r->step); 226 r->start, r->stop, r->step);
226 } 227 }
227 228
228 static PyObject * 229 static PyMemberDef range_members[] = {
229 range_getstart(rangeobject *obj) 230 {"start", T_OBJECT, offsetof(rangeobject, start), READONLY},
230 { 231 {"stop", T_OBJECT, offsetof(rangeobject, stop), READONLY},
231 return obj->start; 232 {"step", T_OBJECT, offsetof(rangeobject, step), READONLY},
232 } 233 {0}
233
234 static PyObject *
235 range_getstop(rangeobject *obj)
236 {
237 return obj->stop;
238 }
239
240 static PyObject *
241 range_getstep(rangeobject *obj)
242 {
243 return obj->step;
244 }
245
246 static PyGetSetDef range_getset[] = {
247 {"start", (getter)range_getstart, NULL, "The start of the range"},
248 {"stop", (getter)range_getstop, NULL, "Where the range stops."},
249 {"step", (getter)range_getstep, NULL, "How much the range jumps."},
250 {0},
251 };
252
253 static PySequenceMethods range_as_sequence = {
254 (lenfunc)range_length, /* sq_length */
GvR 2008/05/02 13:52:47 The latest discussion on the list suggests to remo
255 0, /* sq_concat */
256 0, /* sq_repeat */
257 0, /* sq_item */
258 0, /* sq_slice */
259 0, /* sq_ass_item */
260 0, /* sq_ass_slice */
261 0, /* sq_contains */
262 }; 234 };
263 235
264 static PyObject * range_iter(PyObject *seq); 236 static PyObject * range_iter(PyObject *seq);
265 static PyObject * range_reverse(PyObject *seq); 237 static PyObject * range_reverse(PyObject *seq);
266 238
267 PyDoc_STRVAR(reverse_doc, 239 PyDoc_STRVAR(reverse_doc,
268 "Returns a reverse iterator."); 240 "Returns a reverse iterator.");
269 241
270 static PyMethodDef range_methods[] = { 242 static PyMethodDef range_methods[] = {
271 {"__reversed__", (PyCFunction)range_reverse, METH_NOARGS, 243 {"__reversed__", (PyCFunction)range_reverse, METH_NOARGS,
272 reverse_doc}, 244 reverse_doc},
245 {"__length_hint__", (PyCFunction)range_length_hint, METH_NOARGS,
246 range_length_hint_doc},
273 {NULL, NULL} /* sentinel */ 247 {NULL, NULL} /* sentinel */
274 }; 248 };
275 249
276 PyTypeObject PyRange_Type = { 250 PyTypeObject PyRange_Type = {
277 PyVarObject_HEAD_INIT(&PyType_Type, 0) 251 PyVarObject_HEAD_INIT(&PyType_Type, 0)
278 "range", /* Name of this type */ 252 "range", /* Name of this type */
279 sizeof(rangeobject), /* Basic object size */ 253 sizeof(rangeobject), /* Basic object size */
280 0, /* Item size for varobject */ 254 0, /* Item size for varobject */
281 (destructor)range_dealloc, /* tp_dealloc */ 255 (destructor)range_dealloc, /* tp_dealloc */
282 0, /* tp_print */ 256 0, /* tp_print */
283 0, /* tp_getattr */ 257 0, /* tp_getattr */
284 0, /* tp_setattr */ 258 0, /* tp_setattr */
285 0, /* tp_compare */ 259 0, /* tp_compare */
286 (reprfunc)range_repr, /* tp_repr */ 260 (reprfunc)range_repr, /* tp_repr */
287 0, /* tp_as_number */ 261 0, /* tp_as_number */
288 &range_as_sequence, /* tp_as_sequence */ 262 0, /* tp_as_sequence */
289 0, /* tp_as_mapping */ 263 0, /* tp_as_mapping */
290 0, /* tp_hash */ 264 0, /* tp_hash */
291 0, /* tp_call */ 265 0, /* tp_call */
292 0, /* tp_str */ 266 0, /* tp_str */
293 PyObject_GenericGetAttr, /* tp_getattro */ 267 PyObject_GenericGetAttr, /* tp_getattro */
294 0, /* tp_setattro */ 268 0, /* tp_setattro */
295 0, /* tp_as_buffer */ 269 0, /* tp_as_buffer */
296 Py_TPFLAGS_DEFAULT, /* tp_flags */ 270 Py_TPFLAGS_DEFAULT, /* tp_flags */
297 range_doc, /* tp_doc */ 271 range_doc, /* tp_doc */
298 0, /* tp_traverse */ 272 0, /* tp_traverse */
299 0, /* tp_clear */ 273 0, /* tp_clear */
300 0, /* tp_richcompare */ 274 0, /* tp_richcompare */
301 0, /* tp_weaklistoffset */ 275 0, /* tp_weaklistoffset */
302 range_iter, /* tp_iter */ 276 range_iter, /* tp_iter */
303 0, /* tp_iternext */ 277 0, /* tp_iternext */
304 range_methods, /* tp_methods */ 278 range_methods, /* tp_methods */
305 0, /* tp_members */ 279 range_members, /* tp_members */
306 range_getset, /* tp_getset */ 280 0, /* tp_getset */
GvR 2008/05/02 13:52:47 Please use spaces to indent the comment.
307 0, /* tp_base */ 281 0, /* tp_base */
308 0, /* tp_dict */ 282 0, /* tp_dict */
309 0, /* tp_descr_get */ 283 0, /* tp_descr_get */
310 0, /* tp_descr_set */ 284 0, /* tp_descr_set */
311 0, /* tp_dictoffset */ 285 0, /* tp_dictoffset */
312 0, /* tp_init */ 286 0, /* tp_init */
313 0, /* tp_alloc */ 287 0, /* tp_alloc */
314 range_new, /* tp_new */ 288 range_new, /* tp_new */
315 }; 289 };
316 290
317 /*********************** range Iterator **************************/ 291 /*********************** range Iterator **************************/
318 292
319 /* There are 2 types of iterators, one for C longs, the other for 293 /* There are 2 types of iterators, one for C longs, the other for
320 Python longs (ie, PyObjects). This should make iteration fast 294 Python longs (ie, PyObjects). This should make iteration fast
321 in the normal case, but possible for any numeric value. 295 in the normal case, but possible for any numeric value.
322 */ 296 */
323 297
324 typedef struct { 298 typedef struct {
325 PyObject_HEAD 299 PyObject_HEAD
326 long index; 300 long index;
327 long start; 301 long start;
328 long step; 302 long step;
329 long len; 303 long len;
330 } rangeiterobject; 304 } rangeiterobject;
331 305
332 static PyObject * 306 static PyObject *
333 rangeiter_next(rangeiterobject *r) 307 rangeiter_next(rangeiterobject *r)
334 { 308 {
335 if (r->index < r->len) 309 if (r->index < r->len)
336 return PyLong_FromLong(r->start + (r->index++) * r->step); 310 return PyLong_FromLong(r->start + (r->index++) * r->step);
337 return NULL; 311 return NULL;
338 } 312 }
339 313
340 static PyObject * 314 static PyObject *
341 rangeiter_len(rangeiterobject *r) 315 rangeiter_len(rangeiterobject *r)
342 { 316 {
343 return PyLong_FromLong(r->len - r->index); 317 return PyLong_FromLong(r->len - r->index);
344 } 318 }
345 319
346 typedef struct { 320 typedef struct {
347 PyObject_HEAD 321 PyObject_HEAD
348 PyObject *index; 322 PyObject *index;
349 PyObject *start; 323 PyObject *start;
350 PyObject *step; 324 PyObject *step;
351 PyObject *len; 325 PyObject *length;
352 } longrangeiterobject; 326 } longrangeiterobject;
353 327
354 static PyObject * 328 static PyObject *
355 longrangeiter_len(longrangeiterobject *r, PyObject *no_args) 329 longrangeiter_len(longrangeiterobject *r, PyObject *no_args)
356 { 330 {
357 return PyNumber_Subtract(r->len, r->index); 331 return PyNumber_Subtract(r->length, r->index);
358 } 332 }
359 333
360 static PyObject *rangeiter_new(PyTypeObject *, PyObject *args, PyObject *kw); 334 static PyObject *rangeiter_new(PyTypeObject *, PyObject *args, PyObject *kw);
361 335
362 PyDoc_STRVAR(length_hint_doc, 336 PyDoc_STRVAR(length_hint_doc,
363 "Private method returning an estimate of len(list(it))."); 337 "Private method returning an estimate of len(list(it)).");
364 338
365 static PyMethodDef rangeiter_methods[] = { 339 static PyMethodDef rangeiter_methods[] = {
366 {"__length_hint__", (PyCFunction)rangeiter_len, METH_NOARGS, 340 {"__length_hint__", (PyCFunction)rangeiter_len, METH_NOARGS,
367 length_hint_doc}, 341 length_hint_doc},
368 {NULL, NULL} /* sentinel */ 342 {NULL, NULL} /* sentinel */
369 }; 343 };
370 344
371 PyTypeObject PyRangeIter_Type = { 345 PyTypeObject PyRangeIter_Type = {
372 PyVarObject_HEAD_INIT(&PyType_Type, 0) 346 PyVarObject_HEAD_INIT(&PyType_Type, 0)
373 "range_iterator", /* tp_name */ 347 "range_iterator", /* tp_name */
374 sizeof(rangeiterobject), /* tp_basicsize */ 348 sizeof(rangeiterobject), /* tp_basicsize */
375 0, /* tp_itemsize */ 349 0, /* tp_itemsize */
376 /* methods */ 350 /* methods */
377 (destructor)PyObject_Del, /* tp_dealloc */ 351 (destructor)PyObject_Del, /* tp_dealloc */
378 0, /* tp_print */ 352 0, /* tp_print */
379 0, /* tp_getattr */ 353 0, /* tp_getattr */
380 0, /* tp_setattr */ 354 0, /* tp_setattr */
381 0, /* tp_compare */ 355 0, /* tp_compare */
382 0, /* tp_repr */ 356 0, /* tp_repr */
383 0, /* tp_as_number */ 357 0, /* tp_as_number */
384 0, /* tp_as_sequence */ 358 0, /* tp_as_sequence */
385 0, /* tp_as_mapping */ 359 0, /* tp_as_mapping */
386 0, /* tp_hash */ 360 0, /* tp_hash */
387 0, /* tp_call */ 361 0, /* tp_call */
388 0, /* tp_str */ 362 0, /* tp_str */
389 PyObject_GenericGetAttr, /* tp_getattro */ 363 PyObject_GenericGetAttr, /* tp_getattro */
390 0, /* tp_setattro */ 364 0, /* tp_setattro */
391 0, /* tp_as_buffer */ 365 0, /* tp_as_buffer */
392 Py_TPFLAGS_DEFAULT, /* tp_flags */ 366 Py_TPFLAGS_DEFAULT, /* tp_flags */
393 0, /* tp_doc */ 367 0, /* tp_doc */
394 0, /* tp_traverse */ 368 0, /* tp_traverse */
395 0, /* tp_clear */ 369 0, /* tp_clear */
396 0, /* tp_richcompare */ 370 0, /* tp_richcompare */
397 0, /* tp_weaklistoffset */ 371 0, /* tp_weaklistoffset */
398 PyObject_SelfIter, /* tp_iter */ 372 PyObject_SelfIter, /* tp_iter */
399 (iternextfunc)rangeiter_next, /* tp_iternext */ 373 (iternextfunc)rangeiter_next, /* tp_iternext */
400 rangeiter_methods, /* tp_methods */ 374 rangeiter_methods, /* tp_methods */
401 0, /* tp_members */ 375 0, /* tp_members */
402 0, /* tp_getset */ 376 0, /* tp_getset */
403 0, /* tp_base */ 377 0, /* tp_base */
404 0, /* tp_dict */ 378 0, /* tp_dict */
405 0, /* tp_descr_get */ 379 0, /* tp_descr_get */
406 0, /* tp_descr_set */ 380 0, /* tp_descr_set */
407 0, /* tp_dictoffset */ 381 0, /* tp_dictoffset */
408 0, /* tp_init */ 382 0, /* tp_init */
409 0, /* tp_alloc */ 383 0, /* tp_alloc */
410 rangeiter_new, /* tp_new */ 384 rangeiter_new, /* tp_new */
411 }; 385 };
412 386
413 /* Return number of items in range/xrange (lo, hi, step). step > 0 387 /* Return number of items in range/xrange (lo, hi, step). step > 0
414 * required. Return a value < 0 if &