#!/usr/bin/env python3

import collections
import collections.abc
import numbers

class linspace(collections.abc.Sequence):
    """linspace(start, stop, num) -> linspace object
    
    Return a virtual sequence of num numbers from start to stop (inclusive).
    
    If you need a half-open range, use linspace(start, stop, num+1)[:-1].
    """
    
    def __init__(self, start, stop, num):
        if not isinstance(num, numbers.Integral) or num <= 0:
            raise ValueError('num must be a positive integer')
        self.start, self.stop, self.num = start, stop, num
    def __len__(self):
        return self.num
    def __getitem__(self, i):
        if isinstance(i, slice):
            return [self[x] for x in range(*i.indices(len(self)))]
        if i < 0:
            i = self.num + i
        if i >= self.num:
            raise IndexError('linspace object index out of range')
        return (self.stop*i + self.start*(self.num-i-1))/(self.num-1)
    def __repr__(self):
        return '{}({}, {}, {})'.format(type(self).__name__,
                                       self.start, self.stop, self.num)

if __name__ == '__main__':
    print(list(linspace(1, 2, 5)))

@@ -75,16 +75,102 @@
 umbers%0A%0A
+# This implementation should be %22better%22 than the other... but it's not.%0A# See below.%0A
 class li
@@ -1204,66 +1204,2263 @@
 m)%0A%0A
-if __name__ == '__main__':%0A    print(list(linspace(1, 2, 5
+linspace1 = linspace%0A%0A# This implementation is the naive %22start + i * step%22, with a small%0A# fix to make sure the last value is == stop instead of possibly off%0A# by one digit.%0A#%0A# From a quick test, it's a tiny bit faster--e.g., 6.49us vs. 6.89us for%0A# linspace(1, 2, 5000). It doesn't accumulate rounding errors--for%0A# the same test, every 5th element is different by one digit, and sometimes%0A# the following element, but the one after that is not; when I test with%0A# very small numbers, I get a similar pattern, and linspace2 actually looks%0A# like the better of the two. Also, not multiplying start and stop by i%0A# means that it works with types that can't be multiplied by i but their%0A# differences can (like datetimes), and with types that might overflow%0A# (like fixed-point numbers). And it's exactly what numpy does:%0A# https://github.com/numpy/numpy/blob/v1.9.1/numpy/core/function_base.py#L9%0Aclass linspace(collections.abc.Sequence):%0A    %22%22%22linspace(start, stop, num) -%3E linspace object%0A    %0A    Return a virtual sequence of num numbers from start to stop (inclusive).%0A    %0A    If you need a half-open range, use linspace(start, stop, num+1)%5B:-1%5D.%0A    %22%22%22%0A    %0A    def __init__(self, start, stop, num):%0A        if not isinstance(num, numbers.Integral) or num %3C= 0:%0A            raise ValueError('num must be a positive integer')%0A        self.start, self.stop, self.num = start, stop, num%0A        self.step = (stop-start)/(num-1)%0A    def __len__(self):%0A        return self.num%0A    def __getitem__(self, i):%0A        if isinstance(i, slice):%0A            return %5Bself%5Bx%5D for x in range(*i.indices(len(self)))%5D%0A        if i %3C 0:%0A            i = self.num + i%0A        if i %3E= self.num:%0A            raise IndexError('linspace object index out of range')%0A        if i == self.num-1:%0A            return self.stop%0A        return self.start + i*self.step%0A    def __repr__(self):%0A        return '%7B%7D(%7B%7D, %7B%7D, %7B%7D)'.format(type(self).__name__,%0A                                       self.start, self.stop, self.num)%0A%0Alinspace2 = linspace%0A%0Aif __name__ == '__main__':%0A    print(list(linspace(1, 2, 5)))%0A    import datetime%0A    print(list(map(str, linspace(datetime.datetime(2014, 1, 1),%0A                        datetime.datetime(2015, 1, 1),%0A                        13)
 )))%0A

Switch to "naive" algorithm, as used by numpy