[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.python

Slicing wrapped numpy arrays

Martin Manns

1/13/2008 9:31:00 PM

Hi,

I have created a class that wraps a numpy array of custom objects. I
would like to be able to slice respective objects (without copying the
array if possible).

I have browsed the doc and found some hints at __getitem__. However, I
still do not grasp how to do it. How do I implement __getitem__
correctly?


from numpy import *

class Cell(object):
pass

class Map(object):
def __init__(self, dimensions):
self.generate_map(dimensions)

def generate_map(self, dimensions):
map_range = xrange(reduce(lambda x,y: x*y, dimensions))
self.map = array([Cell() for i in map_range])
self.map = self.map.reshape(dimensions)

mymap = Map((100, 100, 100))
mymap[10:20,15:20,:] # This line should work afterwards


Thanks in advance

Martin
3 Answers

Robert Kern

1/13/2008 10:03:00 PM

0

Martin Manns wrote:
> Hi,
>
> I have created a class that wraps a numpy array of custom objects. I
> would like to be able to slice respective objects (without copying the
> array if possible).
>
> I have browsed the doc and found some hints at __getitem__. However, I
> still do not grasp how to do it. How do I implement __getitem__
> correctly?

> mymap[10:20,15:20,:] # This line should work afterwards

The first thing you should do is simply implement a very basic, nonfunctional
version just to see what objects come in:

In [1]: class Sliceable(object):
...: def __getitem__(self, arg):
...: print arg
...:

From the output of that you should be able to figure out how to process each of
the various inputs that you want to handle.

In [2]: s = Sliceable()

In [3]: s[0]
0

In [4]: s[-1]
-1

In [5]: s[100]
100

In [6]: s[1:10]
slice(1, 10, None)

In [7]: s[1:10:2]
slice(1, 10, 2)

In [8]: s[1:10:-2]
slice(1, 10, -2)

In [9]: s[:10:2,10]
(slice(None, 10, 2), 10)

In [10]: s[:10:2,10:100:10]
(slice(None, 10, 2), slice(10, 100, 10))

In [11]: s[:10:2,10::10]
(slice(None, 10, 2), slice(10, None, 10))

In [12]: s[::2,10::10]
(slice(None, None, 2), slice(10, None, 10))

--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco

Martin Manns

1/13/2008 11:46:00 PM

0

On Sun, 13 Jan 2008 16:03:16 -0600
Robert Kern <robert.kern@gmail.com> wrote:

> Martin Manns wrote:
> > Hi,
> >
> > I have created a class that wraps a numpy array of custom objects. I
> > would like to be able to slice respective objects (without copying
> > the array if possible).
> >
> > I have browsed the doc and found some hints at __getitem__.
> > However, I still do not grasp how to do it. How do I implement
> > __getitem__ correctly?
>
> > mymap[10:20,15:20,:] # This line should work afterwards
>
> The first thing you should do is simply implement a very basic,
> nonfunctional version just to see what objects come in:
>
> In [1]: class Sliceable(object):
> ...: def __getitem__(self, arg):
> ...: print arg
> ...:

I did that and got here:

> (slice(None, None, 2), slice(10, None, 10))

However, I still do not see how I get a Map object that employs a
slice of the array without creating a new Map object.

Martin

Robert Kern

1/14/2008 3:15:00 AM

0

Martin Manns wrote:
> On Sun, 13 Jan 2008 16:03:16 -0600
> Robert Kern <robert.kern@gmail.com> wrote:
>
>> Martin Manns wrote:
>>> Hi,
>>>
>>> I have created a class that wraps a numpy array of custom objects. I
>>> would like to be able to slice respective objects (without copying
>>> the array if possible).
>>>
>>> I have browsed the doc and found some hints at __getitem__.
>>> However, I still do not grasp how to do it. How do I implement
>>> __getitem__ correctly?
>>> mymap[10:20,15:20,:] # This line should work afterwards
>> The first thing you should do is simply implement a very basic,
>> nonfunctional version just to see what objects come in:
>>
>> In [1]: class Sliceable(object):
>> ...: def __getitem__(self, arg):
>> ...: print arg
>> ...:
>
> I did that and got here:
>
>> (slice(None, None, 2), slice(10, None, 10))
>
> However, I still do not see how I get a Map object that employs a
> slice of the array without creating a new Map object.

That's because creating a new Map object is the right thing to do.

Instead of making Map.__init__() generate the map array from the dimensions, it
should just take a preconstructed map array. You can use a @classmethod or just
a factory function to provide an alternate constructor which builds a Map from
the dimensions.

When designing classes, I usually try to do as little computation as possible in
an __init__(). Doing a lot of stuff there limits the ways you can build the
object later. For some classes, this doesn't matter a whole lot, but for data
structures that can be sliced and concatenated or otherwise transformed, you
really want that flexibility.

--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco