Built-in function `range` params discrepancy across versions
I'm sorry if this has already been reported. I'm sure it's very low on any list of priorities but it should be an easy one.
I noticed that when doing a Google search for "python built in functions" I am presented with two official results:
- functions https://docs.python.org/3/library/functions.html
- stdtypes https://docs.python.org/3/library/stdtypes.html
On the functions page, clicking on range takes you to https://docs.python.org/3/library/functions.html#func-range . It looks like, as of 3.11, range accepts step as a kwarg. This is inconsistent with the stdtypes page which shows step as an optional arg through 3.13.
functions:
- 3.10 https://docs.python.org/3.10/library/functions.html#func-range
- 3.11 https://docs.python.org/3.11/library/functions.html#func-range
- 3.12 https://docs.python.org/3.12/library/functions.html#func-range
- 3.13 https://docs.python.org/3.13/library/functions.html#func-range
stdtypes:
- 3.10 https://docs.python.org/3.10/library/stdtypes.html#range
- 3.11 https://docs.python.org/3.11/library/stdtypes.html#range
- 3.12 https://docs.python.org/3.12/library/stdtypes.html#range
- 3.13 https://docs.python.org/3.13/library/stdtypes.html#range
source:
- 3.10 https://github.com/python/cpython/blob/3.10/Objects/rangeobject.c#L159
- 3.11 https://github.com/python/cpython/blob/3.11/Objects/rangeobject.c#L157
- 3.12 https://github.com/python/cpython/blob/3.12/Objects/rangeobject.c#L156
- 3.13 https://github.com/python/cpython/blob/3.13/Objects/rangeobject.c#L158
I didn't see any mention of this change in What’s New In Python 3.11 and it surprised me that a built-in would be changed in such a way.
I pulled a 3.11 docker image and it would seem step is not a kwarg.
docker run -it --rm python:3.11
Python 3.11.10 (main, Oct 19 2024, 04:02:01) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> range(1, 1, step=1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: range() takes no keyword arguments
tl;dr - The functions page incorrectly states that the range function accepts step as a kwarg.
Yeah, you're right, it should be class range(start, stop, step=1, /) on the functions page. PR welcome, we're always looking for new contributors :)
@ZeroIntensity Hmmm... I'm certainly neither an expert nor authority to say what something should (or shouldn't) be; however, range is presented as having an overloaded signature, and I understand why: the function behaves differently depending on the number of args passed, but then I wonder...
From the docs:
If the step argument is omitted, it defaults to 1. If the start argument is omitted, it defaults to 0.
Why is step=1 and not start=0 and how would one write start=0 when start is stop in that case?
(I'm genuinely asking, by the way. Hopefully I'm not coming off as sarcastic.)
It was range(start, stop[, step]) (like it still is in stdtypes) before it was changed in https://github.com/python/cpython/issues/91485. Specifically https://github.com/python/cpython/issues/91485#issuecomment-1098153441.
Back then it was changed to range(start, stop, step=1, /) in https://github.com/python/cpython/pull/96579 and soon later to range(start, stop, step=1) in https://github.com/python/cpython/pull/99476.
Yeah, you're right, it should be
class range(start, stop, step=1, /)on the functions page. PR welcome, we're always looking for new contributors :)
Shouldn't the functions and the stdtypes page be kept in sync, i.e. read exactly the same?
Shouldn't the
functionsand thestdtypespage be kept in sync, i.e. read exactly the same?
I thought about that, but it doesn't seem like the functions page uses the [] notation, so I was hesitant to suggest adding it.
Yes, I see. ISTM that after issue https://github.com/python/cpython/issues/91485 / PR https://github.com/python/cpython/pull/96579, the [] notation was no longer favoured in the functions page, but not all occurences/pages were changed (except a few more, see the PRs attached to the issue).
Hence the asymmetry.
Just wanted to note and see how others think about it :)
But this is most probably not in the scope of this issue ...
What I specifically wanted to draw attention to: https://github.com/python/cpython/pull/99476 dropped many trailing /, e.g.
class:: bool(x=False, /) -> class:: bool(x=False) and here we get the same TypeError: bool() takes no keyword arguments.
Now there is Python Documentation Editorial Board decision: https://discuss.python.org/t/editorial-board-decisions/58580
https://github.com/python/cpython/pull/99476 looks wrong for me.
https://github.com/python/cpython/pull/99476 and its issue(s) are a part of a long history, see also Sergey's links above.
But just changing range here (i.e. a partial revert) and keeping all the other changes of https://github.com/python/cpython/pull/99476 looks worst to me.
IOW: either do nothing or more?
Or am I completely mistaken?
I think that reverting the patch as a whole - is a separate issue. @nedbat, what do you think on this?
But range() issue case shows, that https://github.com/python/cpython/pull/99476 actually not make the functions page "readable again". Syntax like range(start, stop, step=1) suggests to user, that at least the step argument name (in fact, all argument names) is a part of API. And that is wrong.
Take look on the tutorial section 4.9. More on Defining Functions. Hardly after reading about default values and keyword arguments people can expect that function declaration like range(start, stop, step=1) in fact forbid usage with keyword argument step.
If we wish to keep "readable" syntax, we could actually change argument processing to support keyword arguments. This come with a performance penalty, but not too big (1-3% percent with AC).