我认为这个问题基于一个错误的前提:
它是用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
有两种签名: range(stop)
和 range(start, stop[, step])
可能(从技术上)并不准确,但它“解释”了签名如何被解释。
至于为什么:我没有可靠的来源,但我快速扫描了一下我的代码:
我更经常使用 range(stop)
,而不是 range(start, stop)
或 range(start, stop, step)
。因此,单个参数的情况可能是非常“特殊和常见”的,所以对于它有方便之处。在许多场景下都写 range(0, stop)
非常麻烦。
range
有两个不同的签名!!class range(object) | range(stop) -> range 对象 | range(start, stop[, step]) -> range 对象
- Jean-François Fabre