我正在编写一个函数,它接受一个可选列表并将其扩展到指定的长度。我没有将其写为
foo(n, list=None)
,而是想知道如何模拟 Python 范围函数的行为,其工作原理如下:
>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> range(5, 10)
[5, 6, 7, 8, 9]
即先用默认参数。作为参考,尝试天真地设置它会返回语法错误:
def foo(x=10, y):
return x + y
SyntaxError: non-default argument follows default argument
所以我想知道,这是硬编码到范围内的吗?或者可以模仿这种行为吗?
其他人已经展示了如何使用参数计数来完成此操作。不过,如果我自己用 Python 实现它,我会更像这样。
def range(start, limit=None, stride=1):
if limit is None:
start, limit = 0, start
# ...
它们不是真正的关键字参数。
如果有一个参数,那就是极限。
如果有两个参数,第一个是起始值,第二个是限制。
如果有三个参数,第一个是起始值,第二个是限制,第三个是步幅。
用纯Python编写
range
的一种方法是
def range(*args):
if len(args) > 3:
raise TypeError, 'range expected at most 3 arguments, got %d' % len(args)
if len(args) == 2:
return range(args[0], args[1], 1)
if len(args) == 1:
return range(0, args[0], 1)
else:
# actual code for range(start, stop, step) here
Python 通过查看参数的数量来实现
range()
。编写此代码的 Python 版本应该不会太难
来自 rangeobject.c:
static PyObject *
range_new(PyTypeObject *type, PyObject *args, PyObject *kw)
{
rangeobject *obj;
long ilow = 0, ihigh = 0, istep = 1;
unsigned long n;
if (!_PyArg_NoKeywords("xrange()", kw))
return NULL;
if (PyTuple_Size(args) <= 1) {
if (!PyArg_ParseTuple(args,
"l;xrange() requires 1-3 int arguments",
&ihigh))
return NULL;
}
else {
if (!PyArg_ParseTuple(args,
"ll|l;xrange() requires 1-3 int arguments",
&ilow, &ihigh, &istep))
return NULL;
}
if (istep == 0) {
PyErr_SetString(PyExc_ValueError, "xrange() arg 3 must not be zero");
return NULL;
}
n = get_len_of_range(ilow, ihigh, istep);
if (n > (unsigned long)LONG_MAX || (long)n > PY_SSIZE_T_MAX) {
PyErr_SetString(PyExc_OverflowError,
"xrange() result has too many items");
return NULL;
}
obj = PyObject_New(rangeobject, &PyRange_Type);
if (obj == NULL)
return NULL;
obj->start = ilow;
obj->len = (long)n;
obj->step = istep;
return (PyObject *) obj;
}
考虑:
def f(*args):
nargs = len(args)
if nargs == 1:
start = 0
end = args[0]
step = 1
elif nargs == 2:
start = args[0]
end = args[1]
step = 1
elif nargs == 3:
start = args[0]
end = args[1]
step = args[2]
else:
raise TypeError('wrong number of arguments')
return g(start, end, step)