Reputation: 35522
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
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
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
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