the wolf
the wolf

Reputation: 35522

Function definition like range

Suppose I wanted to write a function similar to range

Recall that range has a one argument and 2/3 argument form:

class range(object)
 |  range(stop) -> range object
 |  range(start, stop[, step]) -> range object

If I wanted the method or function to have the same interface, is there a more elegant way than this:

def range_like(*args):
    start,stop,step=[None]*3
    if len(args)==1:
        stop=args[0]
    elif len(args)==2:
        start,stop=args
    elif len(args)==3:
        start,stop,step=args
    else:
        raise ValueError       
    print(start,stop,step)

Upvotes: 5

Views: 226

Answers (3)

andrew cooke
andrew cooke

Reputation: 46882

i would write this as:

def range_like(start=None, stop=None, step=1):
    if stop is None:
        start, stop = stop, start
    ...

if that does what you want?

[update] you can also add:

    if stop is start is None:
        raise ValueError()

also, to use sentinel objects instead of None (this isn't normal in Python, but you see it sometimes):

NOTSET = object()
def range_like(start=NOTSET, stop=NOTSET, step=1):
    if stop is NOTSET:
        start, stop = stop, start

which allows None as an argument.

Upvotes: 4

SheetJS
SheetJS

Reputation: 22905

You can't make an optional argument appear before mandatory arguments.

You can devise workarounds like swapping arguments:

def range_like(s, t=None, u=None):
    if t is None: 
        s,t = t,s

Upvotes: 2

mgibsonbr
mgibsonbr

Reputation: 22007

Not much to suggest here, but one alternative could be using optional arguments and swapping the first two if only one were provided:

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

Upvotes: 5

Related Questions