##
3.3.5 Additional methods for emulation of sequence types

The following methods can be defined to further emulate sequence objects. Immutable sequences methods should only define `__getslice__()`; mutable sequences, should define all three three methods.

`__getslice__`(self, i, j)
  Deprecated since release 2.0. Support slice objects as parameters to the `__getitem__()` method.

  Called to implement evaluation of `self[i:j]`. The returned object should be of the same type as self. Note that missing i or j in the slice expression are replaced by zero or `sys.maxint`, respectively. If negative indexes are used in the slice, the length of the sequence is added to that index. If the instance does not implement the `__len__()` method, an `AttributeError` is raised. No guarantee is made that indexes adjusted this way are not still negative. Indexes which are greater than the length of the sequence are not modified. If no `__getslice__()` is found, a slice object is created instead, and passed to `__getitem__()` instead.

`__setslice__`(self, i, j, sequence)
  Called to implement assignment to `self[i:j]`. Same notes for i and j as for `__getslice__()`.

  This method is deprecated. If no `__setslice__()` is found, a slice object is created instead, and passed to `__setitem__()` instead.

`__delslice__`(self, i, j)
  Called to implement deletion of `self[i:j]`. Same notes for i and j as for `__getslice__()`. This method is deprecated. If no `__delslice__()` is found, a slice object is created instead, and passed to `__delitem__()` instead.

Notice that these methods are only invoked when a single slice with a single colon is used, and the slice method is available. For slice operations involving extended slice notation, or in absence of the slice methods, `__getitem__()`, `__setitem__()` or `__delitem__()` is called with a slice object as argument.

The following example demonstrate how to make your program or module compatible with earlier versions of Python (assuming that methods `__getitem__()`, `__setitem__()` and `__delitem__()` support slice objects as arguments):

      class MyClass:
          ...
          def __getitem__(self, index):
              ...
          def __setitem__(self, index, value):
              ...
          def __delitem__(self, index):
              ...

          if sys.version_info < (2, 0):
              # They won't be defined if version is at least 2.0 final

              def __getslice__(self, i, j):
                  return self[max(0, i):max(0, j):]
              def __setslice__(self, i, j, seq):
                  self[max(0, i):max(0, j):] = seq
              def __delslice__(self, i, j):
                  del self[max(0, i):max(0, j):]
          ...

Note the calls to `max()`; these are actually necessary due to the handling of negative indices before the `__*slice__()` methods are called. When negative indexes are used, the `__*item__()` methods receive them as provided, but the `__*slice__()` methods get a ``cooked'' form of the index values. For each negative index value, the length of the sequence is added to the index before calling the method (which may still result in a negative index); this is the customary handling of negative indexes by the built-in sequence types, and the `__*item__()` methods are expected to do this as well. However, since they should already be doing that, negative indexes cannot be passed in; they must be be constrained to the bounds of the sequence before being passed to the `__*item__()` methods. Calling `max(0, i)` conveniently returns the proper value.