1

What is the proper pythonic way to allow an integer index or a iterator of indexes?

I've implemented a grid widget for the project I'm working on, and I realized I wanted my users to be able to select multiple rows/columns simultaneously. However, I'd like to not require them to use an iterator to indicate a single row/column selection.

Below is some demonstration code that I have working, but it doesn't feel like the right solution:

def toIter ( selection ):
    if selection is None:
        return []
    elif isinstance ( selection, int ):
        return (selection,)
    else:
        return selection

def test ( selection ):
    for col in toIter(selection):
        print(col) # this is where I would act on the selection

test ( None )
test ( 7 ) # user can indicate a specific column selected...
test ( range(3,7) ) # or a tuple/range/list/etc of columns...

EDIT: added the ability to use None to indicate no selection...

2nd EDIT: I'd really think python should be able to do this, but it complains that integer and NoneType aren't iterable:

def test ( selection ):
    for col in selection:
        print(col)
3
  • Numpy has some nifty indexing and slicing features you might find useful for this, and probably a ton of other things you didn't know you needed. Sounds like you might have a matrix. :) Commented Mar 19, 2015 at 20:32
  • I searched SO for an answer to this question, and everybody says that it's not proper to worry about types and they never get around to actually answering the question, so I'm hoping that a concrete example of how it would be useful might get better results, or at least a better explanation of what's wrong with this approach. Commented Mar 19, 2015 at 20:33
  • @Two-BitAlchemist thanks, yes it's a matrix, but my understanding is that numby only deals with numbers, and I actually need to store objects in the 2d array, because I have properties like the contents, the foreground color, background color, font, etc Commented Mar 19, 2015 at 20:34

1 Answer 1

1

You probably just want to override __getitem__ in your widget class, and support integers as well as slices. Something like this:

class Widget(object):
    def __getitem__(self, selection):
        if isinstance(selection, int):
            #return selected col
        elif isinstance(selection, slice):
            #return cols based on selection.start/stop/step
        else:
            raise TypeError('bad selection')

Which you can then use like:

w = Widget()
w[4] # get 4th col
w[8:16] # get 8-16th cols

You could also enhance this to support 2-dimensional access via tuple-of-slices, accessible like w[1:4, 5:8].

Sign up to request clarification or add additional context in comments.

2 Comments

I was just typing up pretty much this same answer. If you want some syntactic sugar on it, you could define a Range class that implements gettem and is returned from a range property in Widget probably with a reference back to the Widget to get the work done.
That's a neat idea, but is there a better way than all these isinstances? Some way that's clean and pythonic that does what my toIter() function is basically doing?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.