classification
Title: Slice indexes passed to __getitem__ are wrapped
Type: behavior Stage:
Components: Interpreter Core Versions:
process
Status: closed Resolution: wont fix
Dependencies: 723806 Superseder:
Assigned To: Nosy List: ajaksu2, belopolsky, connelly, mwh
Priority: normal Keywords:

Created on 2004-06-17 10:22 by connelly, last changed 2009-02-16 20:54 by brett.cannon. This issue is now closed.

Messages (6)
msg60511 - (view) Author: Connelly (connelly) Date: 2004-06-17 10:22
Hi,

When a slice is passed to __getitem__, the indices for
the slice are wrapped by the length of the object
(adding len(self) once to both start index if < 0 and
the end index if < 0).

class C:
  def __getitem__(self, item): print item
  def __len__(self): return 10

>>> x = C()
>>> x[-3]
-3
>>> x[-3:-2]
slice(7, 8, None)

This seems to be incorrect (at least inconsistent).

However, it truly becomes a BUG when one tries to
emulate a list type:

class C:                      # Emulated list type
  def __init__(self, d):
    self.data = d
  def __len__(self):
    return len(self.data)
  def __getitem__(self, item):
    if isinstance(item, slice):
      indices = item.indices(len(self))
      return [self[i] for i in range(*indices)]
    else:
      return self.data[item]

x = [1, 2, 3]
y = C([1, 2, 3])

>>> x[-7:-5]
[]
>>> print y[-7:-5]
[1]                         (incorrect behavior)

Here the item.indices method does the exact same
wrapping process AGAIN.  So indices are wrapped once as
the slice index is constructed and passed to
__getitem__, and again when item.indices is called. 
This makes it impossible to implement a correctly
behaving list data type without using hacks to suppress
this Python bug.

I would advise that you make the slices object passed
to __getitem__ not have its start/end indexes wrapped.

Thanks,
Connelly Barnes
E-mail:
'636f6e6e656c6c796261726e6573407961686f6f2e636f6d'.decode('hex')
msg60512 - (view) Author: Michael Hudson (mwh) (Python committer) Date: 2004-06-17 11:23
Logged In: YES 
user_id=6656

You'll be happier if you make your classes new-style.

I don't know if it's worth changing old-style classes at
this point.  Personally, I'm trying to forget about them
just as quickly as possible :-)
msg60513 - (view) Author: Connelly (connelly) Date: 2004-06-17 21:50
Logged In: YES 
user_id=1039782


I'm not sure what you mean by 'make your classes new-style'.

According to 
http://www.python.org/doc/2.3.4/ref/specialnames.html, the 
__getitem__ method should be used, and the __getslice__ 
method is deprecated.

If you subclass the built-in list type, then the __getitem__ 
method is *not* called when subscripting with a slice.  
Instead, the __getslice__ method is called.  Try it out.

So I can't see any reasonable way to get around this bug.

You can try and modify the class C shown above, so that it 
behaves correctly.  I don't think you will be able to do it 
without putting in special "workaround" code to avoid this 
Python bug.

y = C([1, 2, 3])
>>> print y[-7:-5]         # should be [].

msg60514 - (view) Author: Michael Hudson (mwh) (Python committer) Date: 2004-06-18 10:46
Logged In: YES 
user_id=6656

'make your classes new-style' == subclass object.

>>> class C(object):
...   def __getitem__(self, item): print item
...   def __len__(self): return 10
... 
>>> C()[-3:-2]
slice(-3, -2, None)
msg64309 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2008-03-22 01:19
This looks like a duplicate of issue723806 which was closed as "won't 
fix."
msg82057 - (view) Author: Daniel Diniz (ajaksu2) * (Python triager) Date: 2009-02-14 13:58
Will close this one as a duplicate of #723806 unless someone springs to
its defense.
History
Date User Action Args
2009-02-16 20:54:49brett.cannonsetstatus: open -> closed
resolution: wont fix
2009-02-14 13:58:37ajaksu2setnosy: + ajaksu2
dependencies: + overintelligent slice() behavior on integers
messages: + msg82057
2008-03-22 01:19:06belopolskysetnosy: + belopolsky
type: behavior
messages: + msg64309
components: + Interpreter Core, - None
2004-06-17 10:22:29connellycreate