Thoughts on PEP284
Stephen Horne
$$$$$$$$$$$$$$$$$ at $$$$$$$$$$$$$$$$$$$$.co.uk
Tue Sep 23 12:14:12 EDT 2003
On Tue, 23 Sep 2003 10:22:50 GMT, Alex Martelli <aleax at aleax.it>
wrote:
>> Adding operators to types is always problematic because it defeats
>> Pythons's runtime checking. Assuming that integer slicing would be added
>> to Python, methods that would expect a list of integers would suddenly
>> also work with integers. In most cases, they would not work correctly, but
>> you wouldn't get a meaningful exception.
>
>Careful: in Stephen's proposal, slicing would NOT work on *INTEGERS* --
>rather, it would work on the *INT TYPE ITSELF*, which is a very, very
>different issue.
Exactly - thanks for that.
Actually, Sean Ross posted a prototype implementation which makes a
good point - theres no reason why the sliceable object needs to be the
standard 'int' type in Python as it is now. Maybe a library extended
int type, imported only if used, makes sense. Maybe this is a recipe
or library proposal rather than a language proposal.
>>> Also, one extra feature is that the loop can be infinite (which range
>>> and xrange cannot achieve)...
>>>
>>> for i in int [0:] :
>
>No way, Jose -- now THAT would break things (in admittedly rare
>cases -- a method expecting a list and NOT providing an upper bound
>in the slicing). I'd vote for this to be like int[0:sys.maxint+1]
>(i.e., last item returned is sys.maxint).
True - but boundless generators are already in use.
An implicit sys.maxint(ish) upper bound seems wrong to me. I would
either go with allowing the infinite loop or requiring an explicit
upper bound.
>What Stephen's proposal lacks is rigorous specs of what happens for all
>possible slices -- e.g int[0:-3] isn't immediately intuitive, IMHO;-).
You're right in that this was not intended as a full formal proposal.
But lets see what I can do...
To me, it should be possible to create slices for negative ranges as
easily as positive ranges, so the convention of -1 giving the last
item wouldn't apply.
I already had to look at this issue when I wrapped some C++ container
classes for Python recently (unreleased at present due to the need for
further Pythonicising) - the whole point of doing so was that the
containers allow some more power and flexibility compared with the
Python ones. For instance, my set and (dictionary-like) map classes
are conveniently and efficiently sliceable. But how should the slicing
work?
BTW - there is a price for flexibility - I was very surprised at the
relative speed of a dictionary (at least an order of magnitude faster
than my map) though to be fair I haven't done even trivial
optimisation stuff yet. No, these aren't STL containers.
Anyway, back to the point...
I could have treated slices as specifying subscripts (while the data
structure is *not* a sorted array, it does support reasonably
efficient subscripting) but I felt the upper and lower bounds should
be key values rather than subscripts. But when basing the bounds on
keys, a bound of '-1' logically means a bound with the key value of -1
- not the highest subscript value.
The 'step' value is slightly inconsistent in that it had to be a
subscript-like step (stepping over a specific number of items rather
than a specific key range) as the keys don't always have a sensible
way to interpret these steps. But I'm drifting from the point again.
As a 'set of integers' would IMO logically be sliced by key too, '-1'
should just be a key like any other key, giving...
>>> int [-5:0]
[-5, -4, -3, -2, -1]
>>> int [0:-5]
[]
>>> int [0:-5:-1]
[0, -1, -2, -3, -4]
So to me, the slice should be evaluated as follows...
if step is None : default step to 1
if step == 0 : raise IndexError
if start is None :
either default to zero or raise IndexError, not sure
if stop is None :
either raise IndexError or...
if step > 0 :
default stop to +infinity
else :
default stop to -infinity
Obviously that isn't a real implementation ;-)
--
Steve Horne
steve at ninereeds dot fsnet dot co dot uk
More information about the Python-list
mailing list