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

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