Jim*_*ard 9 python python-3.x python-internals
为什么范围允许非默认参数(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
Run Code Online (Sandbox Code Playgroud)
试图模仿签名是一个明显的违规行为:
def my_range(start=0, stop, end=1):
pass
Run Code Online (Sandbox Code Playgroud)
我知道它实现的事实C可能允许在Pythonland中违反的行为.
我猜这是为了使API更加用户友好,但我没有找到任何来源备份它(源代码并没有说明多少,而PEP 457只说明了多么range奇怪).有谁知道为什么这样做了?
我认为问题是基于一个错误的前提:
我理解它在C中实现的事实可能允许在Pythonland中违反的行为.
它是用C实现的,但这种行为并不违反"Pythonland".文档中的签名是不正确的(实际上不正确,它是"真实签名"的近似 - 可以很容易理解).
例如range,甚至不支持命名参数 - 但根据文档它应该:
>>> range(stop=10)
TypeError: range() does not take keyword arguments
Run Code Online (Sandbox Code Playgroud)
所以实施更多的是:
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
Run Code Online (Sandbox Code Playgroud)
这是有效的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)在整个地方写作会很烦人.