[Python-ideas] Float range class

Guido van Rossum guido at python.org
Sat Jan 10 18:57:38 CET 2015


On Fri, Jan 9, 2015 at 11:03 PM, Andrew Barnert <
abarnert at yahoo.com.dmarc.invalid> wrote:

> On Jan 9, 2015, at 21:13, Guido van Rossum <guido at python.org> wrote:
>
> On Fri, Jan 9, 2015 at 7:29 PM, Andrew Barnert <
> abarnert at yahoo.com.dmarc.invalid> wrote:
>
>> On Jan 9, 2015, at 14:36, Guido van Rossum <guido at python.org> wrote:
>>
>> > (Although the actual signature of linspace gives me a headache. :-)
>>
>> I'm assuming you're not talking about the rested and dtype args (which
>> the stdlib wouldn't need), but rather the fact that endpoint changes the
>> meaning of num (you effectively generate num+1 points and discard the last,
>> instead of generating num points).
>>
>
> All of the above, plus the default to n=50. :-)
>
>
> Oh yeah, that too. I see that you fixed that by just not having a default
> on count, which seems like the best answer.
>
> So, assuming we can get rid of endpoint (either my way or a better way)
> are you happy with the signature now?
>

No, the name still blows, we don't know which module to put it in, and
there's the discussion about how many values to return.


>
> Oh, and the name is odd-sounding for someone not from your world.
>
>
> I move around from world to world; it's weird to me whenever I come back
> to numpy, unless I also need logspace...
>
> I'm guessing that in terms of implementation you might start with this:
>
>     def  linspace(start, stop, num):
>         return [(stop*i + start*(num-i)) / num for i in range(num+1)]
>
>
> That gives a closed range of num+1 values. I think you want a closed range
> of num values (or maybe a half-open range of the first num of num+1
> values). So you want to replace every num with num-1.
>

Not really. I think of this as splitting the range into `num` equal
subranges and returning all the points including the endpoints. I think it
would look really weird if you wanted to split [0, 1] into 10 equal
sections (or 0.1 each) and you had to say 11.


> and then refine as follows:
>
> - make it a lazy sequence, with slicing ability, etc.
>
>
> If you don't need O(1) __contains__ and friends (and I don't think you
> do) that's maybe 5 lines of code with the ABC.
>

If it's in the stdlib it should be modeled after range(), which is
significantly more sophisticated.

OTOH if it's just a one-liner recipe in the docs returning a list is fine.

OT3H __contains__ seems a really bad idea, due to general issues with float
equality.


>
> - numeric tricks to avoid intermediate overflows or numeric instabilities,
> plus optimizations
>
>
> I'll leave this to others. (If no one steps up, I can look at the numpy
> code, but I'm sure this list has people who know it off the top of their
> heads.)
>
> - while still returning exactly the endpoints at the extremes(*)
>
>
> Likewise.
>
> - and better error checking (num must be an integer > 0)
>
>
> Is there anything else that needs to be checked? In particular, start and
> stop have to be something that can be multiplier and divided by integers,
> and added to itself, but that's all kinds of types (numbers, numpy arrays
> of numbers, timedeltas, etc.), so I'm not sure you want to precheck
> anything there.
>

Fair enough.


>
> - and support for start/stop being other numeric types (e.g. complex,
> Fraction, Decimal)
>
>
> That already works out of the box for your implementation, and for the
> obvious conversion to a lazy sequence.
>
> It won't work with datetimes because you can't multiply those by integers
> (you'd need to switch to the naive implementation for those), but it will
> work with timedeltas and all kinds of other types you'd expect to work.
>
> In fact, rather than just say how easy it is, give me 10 minutes to code
> it...
>
> https://github.com/abarnert/linspace
>

I just see more opportunity for bikeshedding. :-(

>
> Then bikeshed about the module it should live in. At least you can shut
> down the bikeshed about the name with "that's what numpy calls it", and
> ditto about the argument order. Just don't add any of the other features of
> the numpy version. :-)
>
> (*) I was going to give the equally naive definition [start + i*step for i
> in range(num+1)] where step is (stop-start)/num, but that would give away
> my naiveté even quicker. :-)
>
> Honestly, I think this is better off as a set of recipies (starting with
the most naive of all and then discussing various refinements for better
accuracy or speed or support of e.g. datetime), with a hefty section on the
off-by-one issue, rather than a stdlib function.

-- 
--Guido van Rossum (python.org/~guido)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20150110/bf5241f3/attachment-0001.html>


More information about the Python-ideas mailing list