1

I will use the range function as the main example in this question.

I use range a lot to generate a list of numbers. However, I use it often with different parameters, specifically a different NUMBER of parameters. It makes me wonder how range easily handles different numbers of parameters and assigns them to their respective value (if they represent the highest value, or the smallest value, or the interval between values). How does range do this? Does it use if statements to handle each scenario, or is there a more efficient way?

1

3 Answers 3

2

At a higher level Python lets you define your functions as:

def foo(*args, **kwargs)

This form of abstract definition enables any number of arguments. The implementation then is the developer's choice. The range function prototype is:

 range(start, stop[, step])

to mean start and stop are expected and step is optional. However, the implementation of this allows for an alternate prototype

 range(stop)

where start defaults to 0 and step defaults to 1. The only thing that makes range look like an overloaded function is its ability to accept an implicit 0 value for start although it is the first argument.

Sign up to request clarification or add additional context in comments.

Comments

1

There are 2 ways to handle a variable number of arguments, you can provide default parameters:
Note: range is not implement this way but is just here for illustration:

def my_range(start=0, stop=None, step=1):
    if stop == None:
        start, stop = 0, start
    while start < stop:
        yield start
        start += step

Now you can call this:

list(my_range(10))          # 0..9
list(my_range(2, 10))       # 2..9
list(my_range(10, step=2))  # 0,2,4,6,8

The other way is to use * for unnamed args and ** for keyword args, the above implemented with *args and **kwargs is a lot messier.

def my_range(*args, **kwargs):
    d = {'start':0, 'stop':None, 'step':1}
    for arg, v in zip(('start', 'stop', 'step'), args):
         d[arg] = v
    d.update(kwargs)
    start, stop, step = (d[arg] for arg in ('start', 'stop', 'step'))
    if stop == None:
        start, stop = 0, start
    while start < stop:
        yield start
        start += step

Obviously the former is much easier to implement, and the latter is usually reserved for special cases and would not be used to implement the above.

Comments

0

Python functions allow a variable number of arguments, either with default argument values:

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

     while (step > 0 and start < stop) or (step < 0 and start > stop):
         yield start
         start += step

(This is not a complete implementation of all the semantics of range). Alternatively, use *args and **kwargs:

def range(*args, **kwargs):
    if len(args) == 1:
        start = 0
        stop = args[0]
        step = 1
    elif len(args) == 2:
        start, stop = args
        step = 1
    elif len(args) == 3:
        start, stop, step = args

    if 'start' in kwargs:
        start = kwargs['start']
    if 'stop' in kwargs:
        stop = kwargs['stop']
    if 'step' in kwargs:
        step = kwargs['step']

     while (step > 0 and start < stop) or (step < 0 and start > stop):
         yield start
         start += step

Note that the standard library range does not accept any keyword arguments, thereby greatly simplifying its implementation.

2 Comments

yours first example is NOT equivalent to range in several cases and the stop condition will fail to step other that 1 in both examples
@Copperfield Thanks, fixed both.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.