【问题标题】:How does the Python range function have a default parameter before the actual one?Python range 函数如何在实际参数之前有一个默认参数?
【发布时间】:2011-10-02 10:32:27
【问题描述】:

所以我正在编写一个函数,它接受一个可选列表并将其扩展到指定的长度。而不是写成 foo(n, list=None) 我想知道如何模拟 Python 的 range 函数的行为,它的工作原理如下:

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

所以我想知道,这是硬编码到范围吗?还是可以模仿这种行为?

【问题讨论】:

  • 你可以计算参数的数量。
  • @eryksun:在这种情况下,我认为这不是很有帮助。

标签: python range overloading default-value


【解决方案1】:

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

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

【讨论】:

  • +1 但这会给出TypeError: range() takes no keyword arguments ` for i in range(limit=len(A), stride=2):`
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    考虑:

    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)
    

    【讨论】:

      【解决方案4】:

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

      【讨论】:

      • 不能正确处理零参数。
      • 无论如何都不允许传递零参数,你会得到一个“范围预期 1 个参数,得到 0”。但是为了完整起见,您有一点,提出这个错误会很好。
      【解决方案5】:

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

      如果有一个论点,那就是极限。

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

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

      【讨论】:

        猜你喜欢
        • 2012-07-25
        • 2017-10-23
        • 2017-11-13
        • 1970-01-01
        • 1970-01-01
        • 2014-07-18
        • 1970-01-01
        • 2016-05-03
        • 1970-01-01
        相关资源
        最近更新 更多