How to implement an optional first argument in Python (play slice ())

Possible duplicate:
How does a built-in range function accept one argument or three?

The Python documentation for slice() contains the following method signatures:

slice (*** stop * ) **
slice (*** start *, stop [ , step ]) **

Here are some examples of creating a slice object with a different number of arguments:

 >>> slice(8) slice(None, 8, None) >>> slice(4, 8) slice(4, 8, None) >>> slice(4, 8, 2) slice(4, 8, 2) 

Note that if you call slice() with a single argument, this argument is used as the stop attribute (the second argument with two or three argument signatures).

Since function overloading does not exist in Python, a typical way to allow a variable number of arguments is to use None as the default value, for example, one attempt to reproduce the above behavior will be as follows:

 class myslice(object): def __init__(self, start, stop=None, step=None): if stop is None and step is None: # only one argument was provided, so use first argument as self.stop self.start = None self.stop = start else: self.start = start self.stop = stop self.step = step def __repr__(self): return 'myslice({}, {}, {})'.format(self.start, self.stop, self.step) 

However, this assumes that None not a value that can be provided for stop , note the following difference in behavior between my implementation and slice() :

 >>> slice(1, None) slice(1, None, None) >>> myslice(1, None) myslice(None, 1, None) 

Is there some other value that I could use instead of None , which indicates that the parameter is definitely not specified? Alternatively, is there a different way to implement this behavior than the default argument values?

Edit: By the way, in CPython slice() implemented in C.

+4
python
source share
1 answer

There are several ways to solve the problem with the default argument. None is the most common, but when None is actually a reasonable value to pass, you can create sentinel :

 sentinel = object() def func(arg=sentinel): if arg is sentinel: arg = "default" do_code() 

Here's a related answer , where there was some discussion about using Ellipsis , since the Ellipsis like ... also solitary.


An alternative way to do this is to use *args and unzip:

 def func(*args): if len(args) == 3: start,stop,step=args elif len(args) == 2: start,stop = args step = None elif len(args) == 1: stop, = args #Need the comma here. Could write `stop = args[0]` instead ... step = start = None else: raise TypeError("Wrong number of arguments!") 
+9
source share

All Articles