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

Ron Adam rrr at ronadam.com
Sat Sep 3 16:27:53 EDT 2005


Bengt Richter wrote:

> 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.

Yes, that's definitely part of it.


> 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 = 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 ;-)

Thanks, I'll play around with it.  ;-)

As you stated before the index is doing two jobs, so limiting it in some 
way may be what is needed.  Here's a few possible (or impossible) options.

(Some of these aren't pretty.)


* Disallow *all* negative values, use values of start/stop to determine 
direction. Indexing from far end needs to be explicit (len(n)-x).

    a[len(a):0]        reverse order
    a[len(a):0:2]      reveres order, even items

(I was wondering why list's couldn't have len,min, and max attribute 
that are updated when ever the list is modified in place of using 
len,min, and max functions? Would the overhead be that much?)

   a[len.a:0]


* Disallow negative index's,  use negative steps to determine indexing 
direction. Order of index's to determine output order.

    a[len(a):0:-1]     forward order, zero based indexing from end.
    a[0:len(a):-1]     reverse order, zero based from end.
    a[0:1:-1]          last item

I works, but single a[-1] is used extremely often.  I don't think having 
to do a[0:1:-1] would be very popular.


* A reverse index symbol/operator could be used ...

    a[~0]  ->   last item,  This works BTW. :-)  ~0 == -1
    a[~1]  ->   next to last item

(Could this be related to the original intended use?)


    a[~0:~0]   slice after end ?.  Doesn't work correctly.

What is needed here is to index from the left instead of the right.

    a[~0] -> item to left of end gap.

*IF* this could be done; I'm sure there's some reason why this won't 
work. ;-), then all indexing operations with '~' could be symmetric with 
all positive indexing operations. Then in Python 3k true negative 
index's could cause an exception... less bugs I bet.  And then negative 
steps could reverse lists with a lot less confusion, keeping that 
functionality as well.

Maybe a[~:~] == a[-len(a):-0]
       a[~:]  == a[-len(a):len(a)]
       a[:~]  == a[0:-0]

       a[~:~] == a[:]

This looks too nice, has it been suggested before?


Ok... a lot of off the top of my head thinking which probably means 
these need to be thought out much better. But that's how a lot of good 
ideas start out.  ;-)

> Regards,
> Bengt Richter





More information about the Python-list mailing list