[Python-Dev] range objects in 3.x

Steven D'Aprano steve at pearwood.info
Tue Sep 27 03:25:48 CEST 2011


Fernando Perez wrote:
> On Sat, 24 Sep 2011 08:13:11 -0700, Guido van Rossum wrote:
> 
>> I expect that to implement a version worthy of the stdlib math module,
>> i.e. that computes values that are correct within 0.5ULP under all
>> circumstances (e.g. lots of steps, or an end point close to the end of
>> the floating point range) we'd need a numerical wizard like Mark
>> Dickinson or Tim Peters (retired). Or maybe we could just borrow numpy's
>> code.
> 
> +1 to using the numpy api, having continuity of API between the two would 
> be great (people work interactively with 'from numpy import *', so having 
> the linspace() call continue to work identically would be a bonus).


The audience for numpy is a small minority of Python users, and they 
tend to be more sophisticated. I'm sure they can cope with two functions 
with different APIs <wink>

While continuity of API might be a good thing, we shouldn't accept a 
poor API just for the sake of continuity. I have some criticisms of the 
linspace API.

numpy.linspace(start, stop, num=50, endpoint=True, retstep=False)

http://docs.scipy.org/doc/numpy/reference/generated/numpy.linspace.html

* It returns a sequence, which is appropriate for numpy but in standard 
Python it should return an iterator or something like a range object.

* Why does num have a default of 50? That seems to be an arbitrary choice.

* It arbitrarily singles out the end point for special treatment. When 
integrating, it is just as common for the first point to be singular as 
the end point, and therefore needing to be excluded.

* If you exclude the end point, the stepsize, and hence the values 
returned, change:

 >>> linspace(1, 2, 4)
array([ 1.        ,  1.33333333,  1.66666667,  2.        ])
 >>> linspace(1, 2, 4, endpoint=False)
array([ 1.  ,  1.25,  1.5 ,  1.75])

This surprises me. I expect that excluding the end point will just 
exclude the end point, i.e. return one fewer point. That is, I expect 
num to count the number of subdivisions, not the number of points.

* The retstep argument changes the return signature from => array to => 
(array, number). I think that's a pretty ugly thing to do. If linspace 
returned a special iterator object, the step size could be exposed as an 
attribute.

* I'm not sure that start/end/count is a better API than start/step/count.

* This one is pure bike-shedding: I don't like the name linspace.


We've gone 20 years without a floating point range in Python. I think we 
should give people a bit of time to pay around with alternative APIs 
rather than just grab the first one that comes along.



-- 
Steven


More information about the Python-Dev mailing list