[MATRIX-SIG] Change slice object?

Janko Hauser jhauser@ifm.uni-kiel.de
Mon, 24 Nov 1997 10:59:11 +0100 (CET)


Konrad Hinsen writes:
 > > Also then there is no need for __getitem__ if one uses indexing. But I
 > > think the method is needed for the for-loop construct, right?
 > 
 > Right. And also for indexing with a single number, e.g. a[5].
 > 
My idea was that exactly this kind of indexing should also be done by 
__getslice__, with the syntax slice(5,6,None). Currently one gets a
mix of two types of indexing (a[5,:,:] for example). But I don't know
the overhead of __getslice__ versus __getitem__

 > > But in every function which deals with slicing, one can be shure to
 > > get only a tuple of slice objects.
 > 
 > True. Still it would break code that relies on the current interpretation.
 > It would probably break my netCDF module, for example.
 > 
This is truly the bad side of such a change, so I will try to build a
class wich can simplify the handling of indices. First I make a
shadow-class for slice (see end of this mail) and than a
composer class wich handles the index argument of __get{slice,item}__.

 > > I don't see, how big the impact of this change would be to the other
 > > sequence objects in python.
 > 
 > None at all, because only arrays use multidimensional indexing and
 > slice objects!
 > 
That's good.

 > > One other idea. What's the way to have a __cmp__ method for slice
 > > objects to test if a slice is completly in another slice or
 > > overlapping at both or only one end.
 > 
 > That could easily be done, but what would it be good for?
I cache array slices from netcdf-files and want to see, if a new
request can be taken from the cached arrays or must be loaded from the
file.


Oh, by the way, I want to ask the more OO-knowing people if this is a
appropiate way to handle attribute access.

I have a class wich represents a region. I can slice the region and
the get variables in that region. I catch the request in __getattr__
and load or calculate the desired variable of that region. For the
user this looks like data-access, because she gets an arrayobject. Or
should something like this be implemented with special functions, to
make it clear, that there is something happening?

r[12,8,:,:] # slice the hole region, internally hold only the
            # information of the currently activ region 
r.temp      # if not cached, load data for this region from file
r.vorticity # load u and v and calculate vorticity in this region
r[13,8,:,:] # next timestep ...

The temp and vorticity fields are actually UserArrays, so they know
more about themselves as normal arrays.


__Janko

################## > nslice.py < ##################################
"""
Provides a class for a little bit more handy slice object 
called nslice.
 
1997 Janko Hauser jhauser@ifm.uni-kiel.de
"""

import Numeric
N=Numeric

def test():
    """
    main()
    Test the nslice class
    """
    a = N.arange(12)
    sl = slice(0,3,None)
    n_sl = nslice(sl)

    print 'TEST for same behavior'
    print a[sl]
    print a[n_sl()]
    sl = slice(0,10,2)
    n_sl.stop = 10
    n_sl.step = 2
    print a[sl]
    print a[n_sl()]

    print 'TEST for comparisson'
    print n_sl, sl, cmp(n_sl,sl)
    n_sl.stop = 11
    print n_sl, sl, cmp(n_sl,sl)
    n_sl.step = 3
    n_sl.stop = 10
    print n_sl, sl, cmp(n_sl,sl)

    print 'TEST for error handling'
    e_sl = nslice((0, 2, 1))
    print 
    return

nsliceError = "Error in nslice:\n"

class nslice:
    """
    slice object with additional methods.

    Currently only access to start,stop and step attributes and a way
    to compare slices.
    """

    def __init__(self, sl):
        """
        Initialize a new instance.
        """
        if (type(sl) == type(1)):
            self.start = sl
            self.stop = sl+1
            self.step = None
        elif (type(sl) == type(slice(0,1,None))):
            self.start = sl.start
            self.stop = sl.stop
            self.step = sl.step
        else:
            raise nsliceError, \
                  "Argument must be an integer or a slice object"

        return

    def __repr__(self):
        return 'n'+str(self.__call__())

    def __call__(self):
        """
        returns the new slice object
        """
        return slice(self.start,
                     self.stop,
                     self.step)

    def __cmp__(self,other):
        """
        gives 0 if both slices are identical
        gives -1 if first slice is part of second one
        gives 1 in all other cases

        Problem is the handling of the step attribute. The above
        is only true if the steps are the same.
        """
        if (type(other) != type(slice(0,1,None))):
            raise nsliceError, \
                  "Both arguments must be slice objects"

        if ((self.start == other.start) and 
            (self.stop == other.stop)):
            return cmp(self.step, other.step)
        elif ((self.start >= other.start) and (self.stop <= other.stop)):
            return -1
        else:
            return 1


if __name__ == "__main__":

    test()

_______________
MATRIX-SIG  - SIG on Matrix Math for Python

send messages to: matrix-sig@python.org
administrivia to: matrix-sig-request@python.org
_______________