range对象支持无穷大数迭代
//object
typedef struct {
PyObject_HEAD
PyObject *start;
PyObject *stop;
PyObject *step;
PyObject *length;
} rangeobject;
新建一个range对象
static PyObject *
range_new(PyTypeObject *type, PyObject *args, PyObject *kw)
{
return range_from_array(
type, _PyTuple_ITEMS(args), //获取参数对象
PyTuple_GET_SIZE(args) //获取参数个数
);
}
static PyObject *
range_from_array(
PyTypeObject *type, //对象
PyObject *const *args, //参数指针
Py_ssize_t num_args //参数个数
)
{
rangeobject *obj;
PyObject *start = NULL, *stop = NULL, *step = NULL;
switch (num_args) {
case 3: //像range(1,10,2)的情况
step = args[2]; //取步长
case 2: //像range(1,10)的情况
start = PyNumber_Index(args[0]);
if (!start) {
return NULL;
}
stop = PyNumber_Index(args[1]);
if (!stop) {
return NULL;
}
step = PyLong_FromLong(1); //步长自动赋1
if (!step) {
return NULL;
}
break;
case 1: //像range(10)的情况
stop = PyNumber_Index(args[0]);
if (!stop) {
return NULL;
}
start = _PyLong_Zero; //起始位置自动赋0
step = _PyLong_One; //步长自动赋1
break;
case 0: //错误
PyExc_TypeError
return NULL;
default: //错误
PyExc_TypeError,
return NULL;
}
obj = make_range_object(type, start, stop, step);//创建对象
if (obj != NULL) {
return (PyObject *) obj;
}
return NULL;
}
//构建range对象
static rangeobject *
make_range_object(PyTypeObject *type, PyObject *start,
PyObject *stop, PyObject *step)
{
rangeobject *obj = NULL;
PyObject *length;
length = compute_range_length(start, stop, step); //计算迭代次数
if (length == NULL) {
return NULL;
}
obj = PyObject_New(rangeobject, type); //分配内存
//设置属性
obj->start = start;
obj->stop = stop;
obj->step = step;
obj->length = length;
return obj;
}
//计算range对象迭代次数
static PyObject*
compute_range_length(PyObject *start, PyObject *stop, PyObject *step)
{
int cmp_result;
PyObject *lo, *hi;
PyObject *diff = NULL;
PyObject *tmp1 = NULL, *tmp2 = NULL, *result;
//step是否大于0
cmp_result = PyObject_RichCompareBool(step, _PyLong_Zero, Py_GT);
//比较错误
if (cmp_result == -1)
return NULL; //返回NULL代表错误
//大于0
if (cmp_result == 1) {
lo = start;
hi = stop;
//小于0,起始位置和结束位置对调,步长转成正数
} else {
lo = stop;
hi = start;
step = PyNumber_Negative(step);
if (!step)
return NULL;
}
//起始位置大于结束位置
cmp_result = PyObject_RichCompareBool(lo, hi, Py_GE);
if (cmp_result != 0) {
if (cmp_result < 0)
return NULL;
return PyLong_FromLong(0);//返回0
}
//tmp = hi - lo
if ((tmp1 = PyNumber_Subtract(hi, lo)) == NULL)
goto Fail;
//diif = tmp1 - 1 不减一可能会超过范围,造成非法访问
if ((diff = PyNumber_Subtract(tmp1, _PyLong_One)) == NULL)
goto Fail;
//tmp2 = diff / step 向下取整除
if ((tmp2 = PyNumber_FloorDivide(diff, step)) == NULL)
goto Fail;
//result = tmp2 + 1 向上取整
if ((result = PyNumber_Add(tmp2, _PyLong_One)) == NULL)
goto Fail;
return result;
Fail:
return NULL;
}
转换为可迭代的range对象
typedef struct {
PyObject_HEAD
long index;
long start;
long step;
long len;
} rangeiterobject;
//long类型的迭代器对象,32位系统中long是4个字节;64位系统中long 是8个字节
typedef struct {
PyObject_HEAD
PyObject *index;
PyObject *start;
PyObject *step;
PyObject *len;
} longrangeiterobject; //长整形的range迭代器对象,支持无穷大迭代
//因为range的迭代时一个时间复杂度高的操作,所以python对此进行了优化
static PyObject *
range_iter(PyObject *seq)
{
rangeobject *r = (rangeobject *)seq;
longrangeiterobject *it;
long lstart, lstop, lstep;
PyObject *int_it;
lstart = PyLong_AsLong(r->start); //尝试转换为long整形8字节
if (lstart == -1 && PyErr_Occurred()) {
goto long_range;
}
lstop = PyLong_AsLong(r->stop); //尝试转换为long整形8字节
if (lstop == -1 && PyErr_Occurred()) {
goto long_range;
}
lstep = PyLong_AsLong(r->step); //尝试转换为long整形8字节
if (lstep == -1 && PyErr_Occurred()) {
goto long_range;
}
//创建rangeiterobject,也就是long整形对象,时间和空间效率相对较好
int_it = fast_range_iter(lstart, lstop, lstep);
if (int_it == NULL && PyErr_ExceptionMatches(PyExc_OverflowError)) {
goto long_range;
}
return (PyObject *)int_it;
long_range:
//创建longrangeiterobject,python通用数字类型,支持无穷大,但时间和空间效率都较差
it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type);
//设置属性
it->start = r->start; //起始位置
it->step = r->step; //步长
it->len = r->length; //长度
it->index = _PyLong_Zero; //索引
return (PyObject *)it;
}
迭代rangeiterobject对象
static PyObject *
rangeiter_next(rangeiterobject *r)
{
//比较迭代次数
if (r->index < r->len)
//返回对应数:起始位置+索引*步长,索引=索引 + 1
return PyLong_FromLong((long)(r->start +
(unsigned long)(r->index++) * r->step));
//结束
return NULL;
}
迭代longrangeiter对象
//实际上和上面的操作一样,只是调用了对象方法,以支持无穷大数计算
static PyObject *
longrangeiter_next(longrangeiterobject *r)
{
PyObject *product, *new_index, *result;
if (PyObject_RichCompareBool(r->index, r->len, Py_LT) != 1)
return NULL;
new_index = PyNumber_Add(r->index, _PyLong_One);
if (!new_index)
return NULL;
product = PyNumber_Multiply(r->index, r->step);
if (!product) {
Py_DECREF(new_index);
return NULL;
}
result = PyNumber_Add(r->start, product);
Py_DECREF(product);
if (result) {
Py_SETREF(r->index, new_index);
}
else {
Py_DECREF(new_index);
}
return result;
}