范围非默认参数遵循默认参数
range non-default parameter follows default one
为什么 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
是奇数)。有谁知道为什么这样做?
我认为这个问题的前提是错误的:
I understand that the fact it is implemented in C probably allows for behavior that would be a violation in Pythonland.
它是用 C 语言实现的,但该行为并不违反 "Pythonland"。文档中的签名只是不正确(实际上不是不正确,它是 "real signature" 的近似值 - 这很容易理解)。
例如 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
内部所做的事情(actual implementation (CPython, Python 3.6.1) 可能略有不同所以不要把 class 当回事) .
然而,像 range(*args)
这样的签名可能对用户没有真正的帮助(尤其是甚至不知道 *args
是什么意思的新用户)。有一份文件说 range
有 2 个签名:range(stop)
和 range(start, stop[, step])
可能(技术上)不准确,但 "explains" 如何解释签名。
至于原因:我没有任何可信的来源,但我很快扫描了我的代码:
我使用 range(stop)
的频率远高于 range(start, stop)
或 range(start, stop, step)
。因此,单参数案例可能 足够特殊和常见 以方便使用。总是到处写 range(0, stop)
会很烦人。
为什么 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
是奇数)。有谁知道为什么这样做?
我认为这个问题的前提是错误的:
I understand that the fact it is implemented in C probably allows for behavior that would be a violation in Pythonland.
它是用 C 语言实现的,但该行为并不违反 "Pythonland"。文档中的签名只是不正确(实际上不是不正确,它是 "real signature" 的近似值 - 这很容易理解)。
例如 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
内部所做的事情(actual implementation (CPython, Python 3.6.1) 可能略有不同所以不要把 class 当回事) .
然而,像 range(*args)
这样的签名可能对用户没有真正的帮助(尤其是甚至不知道 *args
是什么意思的新用户)。有一份文件说 range
有 2 个签名:range(stop)
和 range(start, stop[, step])
可能(技术上)不准确,但 "explains" 如何解释签名。
至于原因:我没有任何可信的来源,但我很快扫描了我的代码:
我使用 range(stop)
的频率远高于 range(start, stop)
或 range(start, stop, step)
。因此,单参数案例可能 足够特殊和常见 以方便使用。总是到处写 range(0, stop)
会很烦人。