the strange arguments of range

12,800

Solution 1

range() takes 1 positional argument and two optional arguments, and interprets these arguments differently depending on how many arguments you passed in.

If only one argument was passed in, it is assumed to be the stop argument, otherwise that first argument is interpreted as the start instead.

In reality, range(), coded in C, takes a variable number of arguments. You could emulate that like this:

def foo(*params):
    if 3 < len(params) < 1:
        raise ValueError('foo takes 1 - 3 arguments')
    elif len(params) == 1
        b = params[0]
    elif:
        a, b = params[:2]
    c = params[2] if len(params) > 2 else 1

but you could also just swap arguments:

def range(start, stop=None, step=1):
    if stop is None:
        start, stop = 0, start

Solution 2

range does not take keyword arguments:

range(start=0,stop=10)
TypeError: range() takes no keyword arguments

it takes 1, 2 or 3 positional arguments, they are evaluated according to their number:

range(stop)              # 1 argument
range(start, stop)       # 2 arguments
range(start, stop, step) # 3 arguments

i.e. it is not possible to create a range with defined stop and step and default start.

Solution 3

def foo(first, second=None, third=1):
     if second is None:
         start, stop, step = 0, first, 1
     else:
         start, stop, step = first, second, third
Share:
12,800
Kritzefitz
Author by

Kritzefitz

Updated on June 04, 2022

Comments

  • Kritzefitz
    Kritzefitz about 2 years

    The range function in python3 takes three arguments. Two of them are optional. So the argument list looks like:

    [start], stop, [step]

    This means (correct me if i'm wrong) there is an optional argument before a non-optional argument. But if i try to define a function like this i get this:

    >>> def foo(a = 1, b, c = 2):
        print(a, b, c)
    SyntaxError: non-default argument follows default argument
    

    Is this something I can't do as a 'normal' python user or can i somehow define such a function? Of course i could do something like

    def foo(a, b = None, c = 2):
        if not b:
            b = a
            a = 1
    

    but for example the help function would then show strange informations. So i really want to know if it's possible do define a function like the built-in range.

  • Rob Smallshire
    Rob Smallshire over 10 years
    Your final example doesn't work. TypeError: range() does not take keyword arguments
  • Martijn Pieters
    Martijn Pieters over 10 years
    @RobSmallshire: The final example is a python replacement for range(). I used keyword arguments to emulate the optional arguments that range() takes; the alternative would be to use a *args catch-all argument and parse up to 2 values from that, but that gets a lot more verbose. That's the first sample in my answer.
  • Martijn Pieters
    Martijn Pieters over 10 years
    @RobSmallshire: The OP tried to emulate the range() behaviour with keyword arguments, the second part is to illustrate how you could implement the behaviour (accept between 1 and 3 positional arguments) by using keyword arguments, in python code.
  • Corey Levinson
    Corey Levinson over 5 years
    So, this is only because the C-coded version of this takes *params instead of actually defining arguments...but why would they code it like that? I don't see a reason to use *params over arguments, especially if the function will return an error if the length of your params is greater than 3. Just seems like very sloppy coding...is it because it's faster? To me it should have been coded as range(PyObject *stop, PyObject *start, PyObject *step) and not deal with this problem. Just seems like a very strange decision to me...
  • Martijn Pieters
    Martijn Pieters over 5 years
    @CoreyLevinson: no, because then you'd have to always specify the start and step values. The Python core developers made an explicit choice to support both range(stop) and range(start, stop).
  • Corey Levinson
    Corey Levinson over 5 years
    @MartijnPieters Why would you always have to specify the start and step values? You can just have in the C function, if (start == NULL && step == NULL) as one of the first lines in the function, right? This will solve the TypeError: range() takes no keyword arguments problem that @eumiro cites in the answer below.
  • Martijn Pieters
    Martijn Pieters over 5 years
    @CoreyLevinson: Why is not taking keyword arguments a problem? Most built-in types don't take keyword arguments.
  • Corey Levinson
    Corey Levinson over 5 years
    @MartijnPieters Because I wanted to write range(start=0,stop=10,step=2) to emphasize the start, stop, and step sizes for anyone who saw my code and was unfamiliar with Python. It's a weird quirk that most built-in types don't take keyword arguments in my opinion. In fact the TypeError was the reason I found this StackOverflow post! I have to use np.linspace to solve my problem now, which is fine, but I just think it's kind of annoying I couldn't use range with keywords.
  • Charlie Parker
    Charlie Parker about 4 years
    is there no way to make the range function take arguments without writing dummy functions or something...?
  • Charlie Parker
    Charlie Parker about 4 years
    Found an answer to my own question: range(*{'start':0,'stop':10,'step':2}.values())