小编典典

范围非默认参数遵循默认值一

python

为什么range允许非默认参数(stop跟随 默认参数(start)?

例子:

>>> r = range(1, 2, 3)
>>> print(r.start, r.stop, r.step)
1 2 3
>>> r = range(10)
>>> print(r.start, r.stop, r.step)
0 10 1

试图模仿签名是一个明显的违反:

def my_range(start=0, stop, end=1):
    pass

据我了解,它的实现C可能允许在Pythonland中违反行为。

我猜测这样做是为了使API更加用户友好,但是,我没有找到任何支持它的源(源代码并不能说明太多,PEP
457
仅说明了range奇怪之处)。有人知道为什么这样做吗?


阅读 220

收藏
2021-01-20

共1个答案

小编典典

我认为这个问题是基于错误的前提:

我知道它是用C语言实现的事实可能允许在Pythonland中违反行为。

它是用C语言实现的,但行为在“ Pythonland”中并不违反。文档中的签名是不正确的(实际上并不正确,它是“真实签名”的近似值-可以很容易理解)。

例如range,甚至不支持命名参数-但根据文档,它应该:

>>> range(stop=10)
TypeError: range() does not take keyword arguments

因此,实现方式大致如下:

class range(object):
    def __init__(self, *args):
        start, step = 0, 1
        if len(args) == 1:
            stop = args[0]
        elif len(args) == 2:
            start, stop = args
        elif len(args) == 3:
            start, stop, step = args

那是有效的Python,并且(大致上)做了range内部的工作(实际实现(CPython,Python
3.6.1)
可能略有不同,因此请不要认真考虑该类)。

但是,像这样的签名range(*args)可能对用户(尤其是甚至不知道*args意味着什么的新用户)并没有真正的帮助。有一个说range有2个签名的文档:range(stop)并且range(start, stop[, step])(在技术上)可能不准确,但是它“解释”了如何解释签名。


至于 原因 :我没有任何可靠的消息来源,但是我迅速扫描了我的代码:

range(stop)range(start, stop)或经常使用range(start, stop, step)。因此,一个论点案例可能很 特殊且普遍,足以 为其带来便利。总是range(0, stop)到处写都是很烦的。

2021-01-20