mirror of https://github.com/python/cpython
add introspection to range objects (closes #9896)
Patch by Daniel Urban.
This commit is contained in:
parent
03b0819389
commit
878ce389a0
|
@ -1042,7 +1042,9 @@ are always available. They are listed here in alphabetical order.
|
||||||
...]``. If *step* is positive, the last element is the largest ``start + i *
|
...]``. If *step* is positive, the last element is the largest ``start + i *
|
||||||
step`` less than *stop*; if *step* is negative, the last element is the
|
step`` less than *stop*; if *step* is negative, the last element is the
|
||||||
smallest ``start + i * step`` greater than *stop*. *step* must not be zero
|
smallest ``start + i * step`` greater than *stop*. *step* must not be zero
|
||||||
(or else :exc:`ValueError` is raised). Example:
|
(or else :exc:`ValueError` is raised). Range objects have read-only data
|
||||||
|
attributes :attr:`start`, :attr:`stop` and :attr:`step` which return the
|
||||||
|
argument values (or their default). Example:
|
||||||
|
|
||||||
>>> list(range(10))
|
>>> list(range(10))
|
||||||
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||||
|
@ -1100,6 +1102,9 @@ are always available. They are listed here in alphabetical order.
|
||||||
sequence of values they define (instead of comparing based on
|
sequence of values they define (instead of comparing based on
|
||||||
object identity).
|
object identity).
|
||||||
|
|
||||||
|
.. versionadded:: 3.3
|
||||||
|
The :attr:`start`, :attr:`stop` and :attr:`step` attributes.
|
||||||
|
|
||||||
|
|
||||||
.. function:: repr(object)
|
.. function:: repr(object)
|
||||||
|
|
||||||
|
|
|
@ -560,6 +560,35 @@ class RangeTest(unittest.TestCase):
|
||||||
range(0) >= range(0)
|
range(0) >= range(0)
|
||||||
|
|
||||||
|
|
||||||
|
def test_attributes(self):
|
||||||
|
# test the start, stop and step attributes of range objects
|
||||||
|
self.assert_attrs(range(0), 0, 0, 1)
|
||||||
|
self.assert_attrs(range(10), 0, 10, 1)
|
||||||
|
self.assert_attrs(range(-10), 0, -10, 1)
|
||||||
|
self.assert_attrs(range(0, 10, 1), 0, 10, 1)
|
||||||
|
self.assert_attrs(range(0, 10, 3), 0, 10, 3)
|
||||||
|
self.assert_attrs(range(10, 0, -1), 10, 0, -1)
|
||||||
|
self.assert_attrs(range(10, 0, -3), 10, 0, -3)
|
||||||
|
|
||||||
|
def assert_attrs(self, rangeobj, start, stop, step):
|
||||||
|
self.assertEqual(rangeobj.start, start)
|
||||||
|
self.assertEqual(rangeobj.stop, stop)
|
||||||
|
self.assertEqual(rangeobj.step, step)
|
||||||
|
|
||||||
|
with self.assertRaises(AttributeError):
|
||||||
|
rangeobj.start = 0
|
||||||
|
with self.assertRaises(AttributeError):
|
||||||
|
rangeobj.stop = 10
|
||||||
|
with self.assertRaises(AttributeError):
|
||||||
|
rangeobj.step = 1
|
||||||
|
|
||||||
|
with self.assertRaises(AttributeError):
|
||||||
|
del rangeobj.start
|
||||||
|
with self.assertRaises(AttributeError):
|
||||||
|
del rangeobj.stop
|
||||||
|
with self.assertRaises(AttributeError):
|
||||||
|
del rangeobj.step
|
||||||
|
|
||||||
def test_main():
|
def test_main():
|
||||||
test.support.run_unittest(RangeTest)
|
test.support.run_unittest(RangeTest)
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/* Range object implementation */
|
/* Range object implementation */
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
|
#include "structmember.h"
|
||||||
|
|
||||||
/* Support objects whose length is > PY_SSIZE_T_MAX.
|
/* Support objects whose length is > PY_SSIZE_T_MAX.
|
||||||
|
|
||||||
|
@ -880,6 +881,13 @@ static PyMethodDef range_methods[] = {
|
||||||
{NULL, NULL} /* sentinel */
|
{NULL, NULL} /* sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static PyMemberDef range_members[] = {
|
||||||
|
{"start", T_OBJECT_EX, offsetof(rangeobject, start), READONLY},
|
||||||
|
{"stop", T_OBJECT_EX, offsetof(rangeobject, stop), READONLY},
|
||||||
|
{"step", T_OBJECT_EX, offsetof(rangeobject, step), READONLY},
|
||||||
|
{0}
|
||||||
|
};
|
||||||
|
|
||||||
PyTypeObject PyRange_Type = {
|
PyTypeObject PyRange_Type = {
|
||||||
PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
||||||
"range", /* Name of this type */
|
"range", /* Name of this type */
|
||||||
|
@ -909,7 +917,7 @@ PyTypeObject PyRange_Type = {
|
||||||
range_iter, /* tp_iter */
|
range_iter, /* tp_iter */
|
||||||
0, /* tp_iternext */
|
0, /* tp_iternext */
|
||||||
range_methods, /* tp_methods */
|
range_methods, /* tp_methods */
|
||||||
0, /* tp_members */
|
range_members, /* tp_members */
|
||||||
0, /* tp_getset */
|
0, /* tp_getset */
|
||||||
0, /* tp_base */
|
0, /* tp_base */
|
||||||
0, /* tp_dict */
|
0, /* tp_dict */
|
||||||
|
|
Loading…
Reference in New Issue