【问题标题】:range non-default parameter follows default one范围非默认参数遵循默认值之一
【发布时间】:2017-05-16 10:39:34
【问题描述】:

为什么范围允许非默认参数(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很奇怪)。有谁知道为什么这样做?

【问题讨论】:

  • 检查文档:range 似乎有 2 个不同的签名! class range(object) | range(stop) -> range object | range(start, stop[, step]) -> range object
  • @JimFasarakisHiliard 关闭,但重新打开。这不是骗局,我应该更好地阅读您的问题。有用的链接:stackoverflow.com/questions/8637130/…
  • @Jean-FrançoisFabre 我想我会的,因为我并不想自己实现它:-)。
  • 为时已晚,为你做到了 :) 现在我无法再次关闭问题,但我想我不会。我最好想出一个答案。
  • 找到了源代码,没有帮助:hg.python.org/cpython/file/3f739f42be51/Objects/rangeobject.c(没有评论解释原因)。我的猜测和你的一样好:只允许启动或步进是没有用的,并且在执行循环时必须指定启动和停止会比 C 循环更糟糕。也许 Raymond Hettinger 或 Alex Martelli 可以回答。

标签: python python-3.x python-internals


【解决方案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 的工作(actual implementation (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) 会很烦人。

【讨论】:

  • 我打算回答(几乎)同样的事情(只是更短,而且没有像那个那样有记录)
  • 实用胜过纯洁。感谢您的撰写;在接下来的几天里,我会对此进行更彻底的调查,如果发现任何异常情况,我会再回来。
  • @JimFasarakisHilliard 你有没有发现什么奇怪的地方? xD
  • 抱歉,@MSeifert,我完全忘记了这一点 :-)
  • @JimFasarakisHilliard random.randrange() 遵循相同的想法,但它是在 Python 中实现的,并带有揭示性的评论“这个代码有点混乱,使它快速......对于常见情况” -我认为这强化了它是一个实际的选择github.com/python/cpython/blob/3.6/Lib/random.py#L173
猜你喜欢
  • 2019-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-04
  • 2018-06-30
  • 1970-01-01
  • 2021-04-08
相关资源
最近更新 更多