Python range 函数如何在实际参数之前有一个默认参数?

问题描述 投票:0回答:5

我正在编写一个函数,它接受一个可选列表并将其扩展到指定的长度。我没有将其写为

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 range default-value
5个回答
12
投票

其他人已经展示了如何使用参数计数来完成此操作。不过,如果我自己用 Python 实现它,我会更像这样。

def range(start, limit=None, stride=1):
    if limit is None:
        start, limit = 0, start
    # ...

10
投票

它们不是真正的关键字参数。

如果有一个参数,那就是极限。

如果有两个参数,第一个是起始值,第二个是限制。

如果有三个参数,第一个是起始值,第二个是限制,第三个是步幅。


8
投票

用纯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

6
投票

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;
}

0
投票

考虑:

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)
© www.soinside.com 2019 - 2024. All rights reserved.