[ python-Bugs-974635 ] Slice indexes passed to __getitem__ are wrapped

SourceForge.net noreply at sourceforge.net
Fri Jun 18 06:46:00 EDT 2004


Bugs item #974635, was opened at 2004-06-17 11:22
Message generated for change (Comment added) made by mwh
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=974635&group_id=5470

Category: None
Group: None
Status: Open
Resolution: None
Priority: 5
Submitted By: Connelly (connelly)
Assigned to: Nobody/Anonymous (nobody)
Summary: Slice indexes passed to __getitem__ are wrapped

Initial Comment:

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')

----------------------------------------------------------------------

>Comment By: Michael Hudson (mwh)
Date: 2004-06-18 11:46

Message:
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)


----------------------------------------------------------------------

Comment By: Connelly (connelly)
Date: 2004-06-17 22:50

Message:
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 [].



----------------------------------------------------------------------

Comment By: Michael Hudson (mwh)
Date: 2004-06-17 12:23

Message:
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 :-)

----------------------------------------------------------------------

You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=974635&group_id=5470



More information about the Python-bugs-list mailing list