Negative array indicies and slice()

Steven D'Aprano steve+comp.lang.python at pearwood.info
Mon Oct 29 07:19:38 EDT 2012


On Mon, 29 Oct 2012 00:54:29 -0700, Andrew wrote:

> Actually, I said in the OP:
> 
> "I also don't understand why slice() is not equivalent to an iterator,
> but can replace an integer in __getitem__() whereas xrange() can't."

Slices and iterators have different purposes and therefore have not been 
made interchangeable. Yes, there are certain similarities between a slice 
and xrange, but there are also significant differences.


> Thank you for the code snippet; I don't think it likely that existing
> programs depend on nor use a negative index and a positive index
> expecting to take a small chunk in the center... 

On the contrary. That is the most straightforward and useful idea of 
slicing, to grab a contiguous slice of items.

Why would you want to grab a slice from the end of the list, and a slice 
from the start of the list, and swap them around? Apart from simulating 
card shuffles and cuts, who does that?


> hence, I would return
> the whole array; Or if someone said [-len(listX) : len(listX)+1 ] I
> would return the whole array twice.

Well, that's one possible interpretation, but it is not the one that 
Python uses. When you create your own language, you can choose whatever 
interpretation seems most useful to you too.



> That's the maximum that is possible.
> If someone could show me a normal/reasonable script which *would* expect
> the other behavior, I'd like to know; compatibility is important.

I'm not entirely sure I understand what you are asking here. 


> My intended inferences about the iterator vs. slice question was perhaps
> not obvious to you; Notice: an iterator is not *allowed* in
> __getitem__().

Actually, you can write __getitem__ for your own classes to accept 
anything you like.

py> class Test:
...     def __getitem__(self, index):
...             return index
...
py> t = Test()
py> t["Hello world"]
'Hello world'
py> t[{'x': None}]
{'x': None}


> The slice class when passed to __getitem__()  was created to merely pass
> two numbers and a stride to __getitem__;  As far as I know slice()
> itself does *nothing* in the actual processing of the elements.  So,
> it's *redundant* functionality, and far worse, it's restrictive.

You say that as if it were a bad thing.


> The philosophy of Python is to have exactly one way to do something when
> possible; so, why create a stand alone class that does nothing an
> existing class could already do, and do it better ?

What existing class is that? It certainly isn't xrange.

Because xrange represents a concrete sequence of numbers, all three of 
start, end and stride must be concrete, known, integers:

py> xrange(4, None, 2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: an integer is required

Whereas slices can trivially include blanks that get filled in only when 
actually used:

py> "hello world"[aslice]
'owrd'
py> "NOBODY expects the Spanish Inquisition!"[aslice]
'D xet h pns nusto!'


So, no, xrange is no substitute for slices. Not even close.


> A simple list of three values would be just as efficient as slice()!

On the contrary, a simple list of three values not only could not do 
everything a slice does, but it's over twice the size!

py> sys.getsizeof([1, 2, 3])
44
py> sys.getsizeof(slice(1, 2, 3))
20


> xrange is more flexible, and can be just as efficient.

Less flexible, less efficient.


[snip]
> In 'C', where Python is written, 

That's a popular misapprehension. Python is written in Java, or Lisp, or 
Haskell, or CLR (dot Net), or RPython, or Ocaml, or Parrot. Each of those 
languages have, or had, at least one Python implementation. Oh, there's 
also a version written in C, or so I have heard.


-- 
Steven



More information about the Python-list mailing list