为什么range允许非默认参数(stop) 跟随 默认参数(start)?
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中违反行为。
C
我猜测这样做是为了使API更加用户友好,但是,我没有找到任何支持它的源(源代码并不能说明太多,PEP 457仅说明了range奇怪之处)。有人知道为什么这样做吗?
range
我认为这个问题是基于错误的前提:
我知道它是用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(*args)
*args
range(stop)
range(start, stop[, step])
至于 原因 :我没有任何可靠的消息来源,但是我迅速扫描了我的代码:
我range(stop)比range(start, stop)或经常使用range(start, stop, step)。因此,一个论点案例可能很 特殊且普遍,足以 为其带来便利。总是range(0, stop)到处写都是很烦的。
range(start, stop)
range(start, stop, step)
range(0, stop)