内置范围函数如何只需一个参数或三个参数?

MWG*_*fin 11 python arguments function range

我想知道,如果有人能告诉我,范围函数如何可以采取:单个参数range(stop),,或者range(start, stop),或者range(start, stop, step).它是否使用variadic类似于*arg收集参数的参数,然后使用一系列if语句根据提供的参数数量分配正确的值?从本质上说,它range()规定,如果有一个参数,然后将其设置成停止争论,或者如果有两个那么他们start,和stop,或者如果有三个然后设置这些作为stop,startstep分别?我想知道如果要在纯Cpython中编写范围,人们会怎么做.谢谢!!!

更新:当我最初提出问题时,我没有澄清,我想知道Cpython中的答案.无论如何,谢谢你的回复!我发现它们都很有启发性.这种反馈让我喜欢stackoverflow和让它如此特别的人!

Mar*_*cin 5

范围采用1、2或3个参数。这可以通过def range(*args)和显式代码实现,当它获得0个或3个以上参数时引发异常。

无法使用默认参数来实现它,因为默认值之后不能再有非默认值,例如def range(start=0, stop, step=1)。从本质上讲,这是因为python必须弄清楚每个调用的含义,因此,如果要使用两个参数进行调用,python将需要一些规则来确定您要覆盖的默认参数。除了没有这样的规则,根本不允许这样做。

如果确实要使用默认参数,则可以执行以下操作:def range(start=0, stop=object(), step=1)并明确检查的类型stop


lqc*_*lqc 5

开源软件的美妙之处在于您只需在源代码中查找:

(TL; DR:是的,它使用varargs)

if (PyTuple_Size(args) <= 1) {
    if (!PyArg_UnpackTuple(args, "range", 1, 1, &stop))
        return NULL;
    stop = PyNumber_Index(stop);
    if (!stop)
        return NULL;
    start = PyLong_FromLong(0);
    if (!start) {
        Py_DECREF(stop);
        return NULL;
    }
    step = PyLong_FromLong(1);
    if (!step) {
        Py_DECREF(stop);
        Py_DECREF(start);
        return NULL;
    }
}
else {
    if (!PyArg_UnpackTuple(args, "range", 2, 3,
                           &start, &stop, &step))
        return NULL;

    /* Convert borrowed refs to owned refs */
    start = PyNumber_Index(start);
    if (!start)
        return NULL;
    stop = PyNumber_Index(stop);
    if (!stop) {
        Py_DECREF(start);
        return NULL;
    }
    step = validate_step(step);    /* Caution, this can clear exceptions */
    if (!step) {
        Py_DECREF(start);
        Py_DECREF(stop);
        return NULL;
    }
}
Run Code Online (Sandbox Code Playgroud)


Kev*_*vin 5

lqc的答案演示了如何range用C实现。您可能仍然好奇range如果Python的内置函数是用Python编写的,将如何实现。我们可以阅读PyPy的源代码来了解一下。从pypy/module/__builtin__/functional.py

def range_int(space, w_x, w_y=NoneNotWrapped, w_step=1):
    """Return a list of integers in arithmetic position from start (defaults
to zero) to stop - 1 by step (defaults to 1).  Use a negative step to
get a list in decending order."""

    if w_y is None:
        w_start = space.wrap(0)
        w_stop = w_x
    else:
        w_start = w_x
        w_stop = w_y
Run Code Online (Sandbox Code Playgroud)

第一个参数 ,space在我看到的所有内置函数中显示为参数,所以我猜测这有点像self用户不直接提供它。其余三个参数中,其中两个具有默认值;因此您可以range使用一个、两个或三个参数进行调用。每个参数的解释方式取决于提供的参数数量。