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

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: __len__ is back! Created 3 months, 3 weeks ago
Right Patch Set: Created 3 months, 4 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:
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
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 Py_ssize_t 201 static Py_ssize_t
198 range_length(rangeobject *r) 202 range_length(rangeobject *r)
199 { 203 {
200 return PyLong_AsSsize_t(r->length); 204 return PyLong_AsSsize_t(r->length);
201 } 205 }
202 206
203 207
204 static PyObject * 208 static PyObject *
205 range_repr(rangeobject *r) 209 range_repr(rangeobject *r)
206 { 210 {
207 Py_ssize_t istep; 211 Py_ssize_t istep;
208 212
209 /* Check for special case values for printing. We don't always 213 /* Check for special case values for printing. We don't always
210 need the step value. We don't care about errors 214 need the step value. We don't care about errors
211 (it means overflow), so clear the errors. */ 215 (it means overflow), so clear the errors. */
212 istep = PyNumber_AsSsize_t(r->step, NULL); 216 istep = PyNumber_AsSsize_t(r->step, NULL);
213 if (istep != 1 || (istep == -1 && PyErr_Occurred())) { 217 if (istep != 1 || (istep == -1 && PyErr_Occurred())) {
214 PyErr_Clear(); 218 PyErr_Clear();
215 } 219 }
216 220
217 if (istep == 1) 221 if (istep == 1)
218 return PyUnicode_FromFormat("range(%R, %R)", r->start, r->stop); 222 return PyUnicode_FromFormat("range(%R, %R)", r->start, r->stop);
219 else 223 else
220 return PyUnicode_FromFormat("range(%R, %R, %R)", 224 return PyUnicode_FromFormat("range(%R, %R, %R)",
221 r->start, r->stop, r->step); 225 r->start, r->stop, r->step);
222 } 226 }
223 227
224 static PyMemberDef range_members[] = { 228 static PyObject *
225 {"start", T_OBJECT, offsetof(rangeobject, start), READONLY}, 229 range_getstart(rangeobject *obj)
226 {"stop", T_OBJECT, offsetof(rangeobject, stop), READONLY}, 230 {
227 {"step", T_OBJECT, offsetof(rangeobject, step), READONLY}, 231 return obj->start;
228 {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 */
229 }; 262 };
230 263
231 static PyObject * range_iter(PyObject *seq); 264 static PyObject * range_iter(PyObject *seq);
232 static PyObject * range_reverse(PyObject *seq); 265 static PyObject * range_reverse(PyObject *seq);
233 266
234 PyDoc_STRVAR(reverse_doc, 267 PyDoc_STRVAR(reverse_doc,
235 "Returns a reverse iterator."); 268 "Returns a reverse iterator.");
236
237 static PySequenceMethods range_as_sequence = {
238 (lenfunc)range_length, /* sq_length */
239 0, /* sq_concat */
240 0, /* sq_repeat */
241 0, /* sq_item */
242 0, /* sq_slice */
243 0, /* sq_ass_item */
244 0, /* sq_ass_slice */
245 0, /* sq_contains */
246 0, /* sq_inplace_concat */
247 0, /* sq_inplace_repeat */
248 };
249 269
250 static PyMethodDef range_methods[] = { 270 static PyMethodDef range_methods[] = {
251 {"__reversed__", (PyCFunction)range_reverse, METH_NOARGS, 271 {"__reversed__", (PyCFunction)range_reverse, METH_NOARGS,
252 reverse_doc}, 272 reverse_doc},
253 {NULL, NULL} /* sentinel */ 273 {NULL, NULL} /* sentinel */
254 }; 274 };
255 275
256 PyTypeObject PyRange_Type = { 276 PyTypeObject PyRange_Type = {
257 PyVarObject_HEAD_INIT(&PyType_Type, 0) 277 PyVarObject_HEAD_INIT(&PyType_Type, 0)
258 "range", /* Name of this type */ 278 "range", /* Name of this type */
259 sizeof(rangeobject), /* Basic object size */ 279 sizeof(rangeobject), /* Basic object size */
260 0, /* Item size for varobject */ 280 0, /* Item size for varobject */
261 (destructor)range_dealloc, /* tp_dealloc */ 281 (destructor)range_dealloc, /* tp_dealloc */
262 0, /* tp_print */ 282 0, /* tp_print */
263 0, /* tp_getattr */ 283 0, /* tp_getattr */
264 0, /* tp_setattr */ 284 0, /* tp_setattr */
265 0, /* tp_compare */ 285 0, /* tp_compare */
266 (reprfunc)range_repr, /* tp_repr */ 286 (reprfunc)range_repr, /* tp_repr */
267 0, /* tp_as_number */ 287 0, /* tp_as_number */
268 &range_as_sequence, /* tp_as_sequence */ 288 &range_as_sequence, /* tp_as_sequence */
269 0, /* tp_as_mapping */ 289 0, /* tp_as_mapping */
270 0, /* tp_hash */ 290 0, /* tp_hash */
271 0, /* tp_call */ 291 0, /* tp_call */
272 0, /* tp_str */ 292 0, /* tp_str */
273 PyObject_GenericGetAttr, /* tp_getattro */ 293 PyObject_GenericGetAttr, /* tp_getattro */
274 0, /* tp_setattro */ 294 0, /* tp_setattro */
275 0, /* tp_as_buffer */ 295 0, /* tp_as_buffer */
276 Py_TPFLAGS_DEFAULT, /* tp_flags */ 296 Py_TPFLAGS_DEFAULT, /* tp_flags */
277 range_doc, /* tp_doc */ 297 range_doc, /* tp_doc */
278 0, /* tp_traverse */ 298 0, /* tp_traverse */
279 0, /* tp_clear */ 299 0, /* tp_clear */
280 0, /* tp_richcompare */ 300 0, /* tp_richcompare */
281 0, /* tp_weaklistoffset */ 301 0, /* tp_weaklistoffset */
282 range_iter, /* tp_iter */ 302 range_iter, /* tp_iter */
283 0, /* tp_iternext */ 303 0, /* tp_iternext */
284 range_methods, /* tp_methods */ 304 range_methods, /* tp_methods */
285 range_members, /* tp_members */ 305 0, /* tp_members */
286 0, /* tp_getset */ 306 range_getset, /* tp_getset */
GvR 2008/05/02 13:52:47 Please use spaces to indent the comment.
287 0, /* tp_base */ 307 0, /* tp_base */
288 0, /* tp_dict */ 308 0, /* tp_dict */
289 0, /* tp_descr_get */ 309 0, /* tp_descr_get */
290 0, /* tp_descr_set */ 310 0, /* tp_descr_set */
291 0, /* tp_dictoffset */ 311 0, /* tp_dictoffset */
292 0, /* tp_init */ 312 0, /* tp_init */
293 0, /* tp_alloc */ 313 0, /* tp_alloc */
294 range_new, /* tp_new */ 314 range_new, /* tp_new */
295 }; 315 };
296 316
297 /*********************** range Iterator **************************/ 317 /*********************** range Iterator **************************/
298 318
299 /* 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
300 Python longs (ie, PyObjects). This should make iteration fast 320 Python longs (ie, PyObjects). This should make iteration fast
301 in the normal case, but possible for any numeric value. 321 in the normal case, but possible for any numeric value.
302 */ 322 */
303 323
304 typedef struct { 324 typedef struct {
305 PyObject_HEAD 325 PyObject_HEAD
306 long index; 326 long index;
307 long start; 327 long start;
308 long step; 328 long step;
309 long len; 329 long len;
310 } rangeiterobject; 330 } rangeiterobject;
311 331
312 static PyObject * 332 static PyObject *
313 rangeiter_next(rangeiterobject *r) 333 rangeiter_next(rangeiterobject *r)
314 { 334 {
315 if (r->index < r->len) 335 if (r->index < r->len)
316 return PyLong_FromLong(r->start + (r->index++) * r->step); 336 return PyLong_FromLong(r->start + (r->index++) * r->step);
317 return NULL; 337 return NULL;
318 } 338 }
319 339
320 static PyObject * 340 static PyObject *
321 rangeiter_len(rangeiterobject *r) 341 rangeiter_len(rangeiterobject *r)
322 { 342 {
323 return PyLong_FromLong(r->len - r->index); 343 return PyLong_FromLong(r->len - r->index);
324 } 344 }
325 345
326 typedef struct { 346 typedef struct {
327 PyObject_HEAD 347 PyObject_HEAD
328 PyObject *index; 348 PyObject *index;
329 PyObject *start; 349 PyObject *start;
330 PyObject *step; 350 PyObject *step;
331 PyObject *length; 351 PyObject *len;
332 } longrangeiterobject; 352 } longrangeiterobject;
333 353
334 static PyObject * 354 static PyObject *
335 longrangeiter_len(longrangeiterobject *r, PyObject *no_args) 355 longrangeiter_len(longrangeiterobject *r, PyObject *no_args)
336 { 356 {
337 return PyNumber_Subtract(r->length, r->index); 357 return PyNumber_Subtract(r->len, r->index);
338 } 358 }
339 359
340 static PyObject *rangeiter_new(PyTypeObject *, PyObject *args, PyObject *kw); 360 static PyObject *rangeiter_new(PyTypeObject *, PyObject *args, PyObject *kw);
341 361
342 PyDoc_STRVAR(length_hint_doc, 362 PyDoc_STRVAR(length_hint_doc,
343 "Private method returning an estimate of len(list(it))."); 363 "Private method returning an estimate of len(list(it)).");
344 364
345 static PyMethodDef rangeiter_methods[] = { 365 static PyMethodDef rangeiter_methods[] = {
346 {"__length_hint__", (PyCFunction)rangeiter_len, METH_NOARGS, 366 {"__length_hint__", (PyCFunction)rangeiter_len, METH_NOARGS,
347 length_hint_doc}, 367 length_hint_doc},
348 {NULL, NULL} /* sentinel */ 368 {NULL, NULL} /* sentinel */
349 }; 369 };
350 370
351 PyTypeObject PyRangeIter_Type = { 371 PyTypeObject PyRangeIter_Type = {
352 PyVarObject_HEAD_INIT(&PyType_Type, 0) 372 PyVarObject_HEAD_INIT(&PyType_Type, 0)
353 "range_iterator", /* tp_name */ 373 "range_iterator", /* tp_name */
354 sizeof(rangeiterobject), /* tp_basicsize */ 374 sizeof(rangeiterobject), /* tp_basicsize */
355 0, /* tp_itemsize */ 375 0, /* tp_itemsize */
356 /* methods */ 376 /* methods */
357 (destructor)PyObject_Del, /* tp_dealloc */ 377 (destructor)PyObject_Del, /* tp_dealloc */
358 0, /* tp_print */ 378 0, /* tp_print */
359 0, /* tp_getattr */ 379 0, /* tp_getattr */
360 0, /* tp_setattr */ 380 0, /* tp_setattr */
361 0, /* tp_compare */ 381 0, /* tp_compare */
362 0, /* tp_repr */ 382 0, /* tp_repr */
363 0, /* tp_as_number */ 383 0, /* tp_as_number */
364 0, /* tp_as_sequence */ 384 0, /* tp_as_sequence */
365 0, /* tp_as_mapping */ 385 0, /* tp_as_mapping */
366 0, /* tp_hash */ 386 0, /* tp_hash */
367 0, /* tp_call */ 387 0, /* tp_call */
368 0, /* tp_str */ 388 0, /* tp_str */
369 PyObject_GenericGetAttr, /* tp_getattro */ 389 PyObject_GenericGetAttr, /* tp_getattro */
370 0, /* tp_setattro */ 390 0, /* tp_setattro */
371 0, /* tp_as_buffer */ 391 0, /* tp_as_buffer */
372 Py_TPFLAGS_DEFAULT, /* tp_flags */ 392 Py_TPFLAGS_DEFAULT, /* tp_flags */
373 0, /* tp_doc */ 393 0, /* tp_doc */
374 0, /* tp_traverse */ 394 0, /* tp_traverse */
375 0, /* tp_clear */ 395 0, /* tp_clear */
376 0, /* tp_richcompare */ 396 0, /* tp_richcompare */
377 0, /* tp_weaklistoffset */ 397 0, /* tp_weaklistoffset */
378 PyObject_SelfIter, /* tp_iter */ 398 PyObject_SelfIter, /* tp_iter */
379 (iternextfunc)rangeiter_next, /* tp_iternext */ 399 (iternextfunc)rangeiter_next, /* tp_iternext */
380 rangeiter_methods, /* tp_methods */ 400 rangeiter_methods, /* tp_methods */
381 0, /* tp_members */ 401 0, /* tp_members */
382 0, /* tp_getset */ 402 0, /* tp_getset */
383 0, /* tp_base */ 403 0, /* tp_base */
384 0, /* tp_dict */ 404 0, /* tp_dict */
385 0, /* tp_descr_get */ 405 0, /* tp_descr_get */
386 0, /* tp_descr_set */ 406 0, /* tp_descr_set */
387 0, /* tp_dictoffset */ 407 0, /* tp_dictoffset */
388 0, /* tp_init */ 408 0, /* tp_init */
389 0, /* tp_alloc */ 409 0, /* tp_alloc */
390 rangeiter_new, /* tp_new */ 410 rangeiter_new, /* tp_new */
391 }; 411 };
392 412
393 /* 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
394 * required. Return a value < 0 if & only if the true value is too 414 * required. Return a value < 0 if & only if the true value is too