Bug in string.find; was: Re: Proposed PEP: New style indexing,was Re: Bug in slice type

Bengt Richter bokr at oz.net
Fri Sep 2 22:53:52 EDT 2005


On Wed, 31 Aug 2005 14:16:28 GMT, Ron Adam <rrr at ronadam.com> wrote:
[...]
>
>The problem with negative index's are that positive index's are zero 
>based, but negative index's are 1 based.  Which leads to a non 
>symmetrical situations.
>
>Note that you can insert an item before the first item using slices. But 
>not after the last item without using len(list) or some value larger 
>than len(list).

IMO the problem is that the index sign is doing two jobs, which for zero-based
reverse indexing have to be separate: i.e., to show direction _and_ a _signed_
offset which needs to be realtive to the direction and base position.

A list-like class, and an option to use a zero-based reverse index will illustrate:

>>> class Zbrx(object):
 ...     def __init__(self, value=0):
 ...         self.value = value
 ...     def __repr__(self): return 'Zbrx(%r)'%self.value
 ...     def __sub__(self, other): return Zbrx(self.value - other)
 ...     def __add__(self, other): return Zbrx(self.value + other)
 ...
 >>> class Zbrxlist(object):
 ...     def normslc(self, slc):
 ...         sss = [slc.start, slc.stop, slc.step]
 ...         for i,s in enumerate(sss):
 ...             if isinstance(s, Zbrx): sss[i] = len(self.value)-1-s.value
 ...         return tuple(sss), slice(*sss)
 ...     def __init__(self, value):
 ...         self.value = value
 ...     def __getitem__(self, i):
 ...         if isinstance(i, int):
 ...             return '[%r]: %r'%(i, self.value[i])
 ...         elif isinstance(i, Zbrx):
 ...             return '[%r]: %r'%(i, self.value[len(self.value)-1-i.value])
 ...         elif isinstance(i, slice):
 ...             sss, slc = self.normslc(i)
 ...             return '[%r:%r:%r]: %r'%(sss+ (list.__getitem__(self.value, slc),))
 ...     def __setitem__(self, i, v):
 ...         if isinstance(i, int):
 ...             list.__setitem__(self, i, v)
 ...         elif isinstance(i, slice):
 ...             sss, slc = self.normslc(i)
 ...             list.__setitem__(self.value, slc, v)
 ...     def __repr__(self): return 'Zbrxlist(%r)'%self.value
 ...
 >>> zlast = Zbrx(0)
 >>> zbr10 = Zbrxlist(range(10))
 >>> zbr10[zlast]
 '[Zbrx(0)]: 9'
 >>> zbr10[zlast:]
 '[9:None:None]: [9]'
 >>> zbr10[zlast:zlast] = ['end']
 >>> zbr10
 Zbrxlist([0, 1, 2, 3, 4, 5, 6, 7, 8, 'end', 9])
 >>> ztop = Zbrx(-1)
 >>> zbr10[ztop:ztop] = ['final']
 >>> zbr10
 Zbrxlist([0, 1, 2, 3, 4, 5, 6, 7, 8, 'end', 9, 'final'])
 >>> zbr10[zlast:]
 "[11:None:None]: ['final']"
 >>> zbr10[zlast]
 "[Zbrx(0)]: 'final'"
 >>> zbr10[zlast+1]
 '[Zbrx(1)]: 9'
 >>> zbr10[zlast+2]
 "[Zbrx(2)]: 'end'"

>
> >>> a = list('abcde')
> >>> a[len(a):len(a)] = ['end']
> >>> a
>['a', 'b', 'c', 'd', 'e', 'end']
>
> >>> a[-1:-1] = ['last']
> >>> a
>['a', 'b', 'c', 'd', 'e', 'last', 'end']     # Second to last.
>
> >>> a[100:100] = ['final']
> >>> a
>['a', 'b', 'c', 'd', 'e', 'last', 'end', 'final']
>

 >>> a = Zbrxlist(list('abcde'))
 >>> a
 Zbrxlist(['a', 'b', 'c', 'd', 'e'])

Forgot to provide a __len__ method ;-)
 >>> a[len(a.value):len(a.value)] = ['end']
 >>> a
 Zbrxlist(['a', 'b', 'c', 'd', 'e', 'end'])

lastx refers to the last items by zero-based reverse indexing
 >>> a[lastx]
 "[Zbrx(0)]: 'end'"
 >>> a[lastx:lastx] = ['last']
 >>> a
 Zbrxlist(['a', 'b', 'c', 'd', 'e', 'last', 'end'])

As expected, or do you want to define different semantics?
You still need to spell len(a) in the slice somehow to indicate
beond the top. E.g.,

 >>> a[lastx-1:lastx-1] = ['final']
 >>> a
 Zbrxlist(['a', 'b', 'c', 'd', 'e', 'last', 'end', 'final'])

Perhaps you can take the above toy and make something that works
they way you had in mind? Nothing like implementation to give
your ideas reality ;-)

Regards,
Bengt Richter



More information about the Python-list mailing list