Method(s) called by square brackets, slice objects

J

John Ladasky

I would like to build a multi-dimensional array that allows numpy-style indexing and, ideally, uses Python's familiar square-bracket and slice notations.

For example, if I declare a two-dimensional array object, x, then x[4,7] retrieves the element located at the 4th row and the 7th column. If I ask for x[3:6,1:3], I get a 3 x 2 array object consisting of the intersection of the 3rd-5th rows, and the 1st-2nd columns, of x.

In this case I'm not allowed to use numpy, I have to restrict myself to thestandard library. I thought that I might achieve the desired behavior by defining an object with specific __getitem__ and/or __getslice__ methods. However, the documentation of these methods that I am reading suggests thatthe arguments are pre-parsed into certain formats which may not allow me to do things numpy's way. Is this true?
 
E

Ethan Furman

I would like to build a multi-dimensional array that allows numpy-style
indexing and, ideally, uses Python's familiar square-bracket and slice
notations.

For example, if I declare a two-dimensional array object, x, then x[4,7]
retrieves the element located at the 4th row and the 7th column. If I
ask for x[3:6,1:3], I get a 3 x 2 array object consisting of the inter-
section of the 3rd-5th rows, and the 1st-2nd columns, of x.

In this case I'm not allowed to use numpy, I have to restrict myself to
the standard library. I thought that I might achieve the desired behavior
by defining an object with specific __getitem__ and/or __getslice__ methods.
However, the documentation of these methods that I am reading suggests that
the arguments are pre-parsed into certain formats which may not allow me to
do things numpy's way. Is this true?

Nope. Whatever you put between the square brackets is what gets passed into __getitem__; the only caveat is that
anything with : will be turned into a slice:

Python 2.7.3 (default, Sep 26 2012, 21:51:14)
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
--> class GetIndex(object):
.... def __getitem__(self, thing):
.... print thing
.... return None
....
--> test = GetIndex()

--> test[1]
1

--> test [1,2]
(1, 2)

--> test[1:3, 4:5]
(slice(1, 3, None), slice(4, 5, None))

--> test[range(3)]
[0, 1, 2]
 
S

Steven D'Aprano

I would like to build a multi-dimensional array that allows numpy-style
indexing and, ideally, uses Python's familiar square-bracket and slice
notations.

For example, if I declare a two-dimensional array object, x, then x[4,7]
retrieves the element located at the 4th row and the 7th column. If I
ask for x[3:6,1:3], I get a 3 x 2 array object consisting of the
intersection of the 3rd-5th rows, and the 1st-2nd columns, of x.

In this case I'm not allowed to use numpy, I have to restrict myself to
the standard library. I thought that I might achieve the desired
behavior by defining an object with specific __getitem__ and/or
__getslice__ methods.

Use __getitem__, __getslice__ is deprecated in Python 2 and gone in
Python 3.

https://docs.python.org/2/reference/datamodel.html#object.__getslice__

However, the documentation of these methods that
I am reading suggests that the arguments are pre-parsed into certain
formats which may not allow me to do things numpy's way. Is this true?

Why don't you try it in the interactive interpreter and see?


py> class Test(object):
.... def __getitem__(self, thing):
.... print thing
....
py> obj = Test()
py> obj[1]
1
py> obj[1:2]
slice(1, 2, None)
py> obj[1:2:3]
slice(1, 2, 3)
py> obj[1,5:2:3]
(1, slice(5, 2, 3))
py> obj[1:2:3,4:5:6]
(slice(1, 2, 3), slice(4, 5, 6))
py> obj[1,2,3]
(1, 2, 3)
py> obj[1,2,"spam"]
(1, 2, 'spam')
py> obj[1,2,"spam":"eggs",3]
(1, 2, slice('spam', 'eggs', None), 3)
 
J

John Ladasky

Thanks to both Ethan and Steven for their replies.

Steven: I was trying to use the interpreter and wasn't getting results that I understood -- because I didn't know that __getslice__ was simply gone in Python 3. I implemented a __getslice__ method in my subclass that never got called.

Ethan: I saw that slice objects were being sent to __getitem__, but that confused me as I thought that its purpose, as implied by the method name, was to return a SINGLE item.

OK, I think that I've got all that sorted out!
 
T

Terry Reedy

Thanks to both Ethan and Steven for their replies.

Steven: I was trying to use the interpreter and wasn't getting results that I understood -- because I didn't know that __getslice__ was simply gone in Python 3. I implemented a __getslice__ method in my subclass that never got called.

Ethan: I saw that slice objects were being sent to __getitem__, but that confused me as I thought that its purpose, as implied by the method name, was to return a SINGLE item.

A slice is a single sequence object. Sequences can result from any of
index lookup, key lookup, or slicings.

The backstory is that slicing originally supported only start and stop
positions. The 3 __xyzslice__ had separate start and stop parameters
instead of the 1 index/key parameter of __xyzitem__. Strides and the
slice class were introduced for the benefit of numerical python. When
they were 'mainstreamed' into regular python, the __xyzslice__ methods
were deprecated (in 2.0) as a single slice object can just as well be
passed to __xyzitem__.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,994
Messages
2,570,222
Members
46,810
Latest member
Kassie0918

Latest Threads

Top