tags:

views:

167

answers:

3

How can I resolve this?

>>> class unslice:
...     def __getitem__(self, item): print type(item), ":", item
...
>>> u = unslice()
>>> u[1,2]    # using an extended slice
<type 'tuple'> : (1, 2)
>>> t = (1, 2)
>>> u[t]  # or passing a plain tuple
<type 'tuple'> : (1, 2)

Rational:

I'm currently overengineering a sorted associative collection with the ability to return ranges of items. It is quite likely that I will want to store tuples of small integers (or even more pathologically wierd values like Ellipsis) in the collection (as keys), and will need some kind of sane way of differentiating extended slices from plain keys

In the one-dimensional case, it's sort of a non-issue. I can't think of any real reason I would want to collect values of type slice, especially since xrange values are functionally similar and more recognizable to pythonistas (in my judgement). All other extended slice constructs are tuples of slice, Ellipsis or plain-old python values

No other type of extended slice seems to be in common use for any kind of collection except multidimensional arrays as in NumPy.

I do need to support n-dimensional axes, similar to oct-trees or GiS indices.

+3  A: 

Since there is no way to differentiate between the calls u[x,y] and u[(x,y)], you should shift one of the two operations you are trying to define off to an actual method. You know, something named u.slice() or u.range() or u.getslice() or u.getrange() or something like that.

Actually, when writing my own programs, I generally find that when I'm trying to overload a Python operation with two quite distinct semantics, it means that both of the things I am doing need to be turned into named methods! Because if the two are so similar in meaning that neither one has an obviously superior claim to getting to use the braces [] getitem shortcut, then probably my code will be more readable if both operations get real, readable, explicit method names.

But, it's hard to say more since you haven't told us how on earth you've gotten into this mess. Why would you want to both store things under tuples and get ranges of things? One suspects you are doing something to complicated to begin with. :-)

Oh, and other languages with this problem make you say a[1][2] to do multi-dimensional access to easily distinguish from a[1,2]. Just so you know there's another option.

Brandon Craig Rhodes
a[1][2] would be very difficult to make work in the case i'm looking at. Specifically, say i'm collecting invoices sorted by date AND amount. I might want to do invoices[strptime("2008apr","%Y%b"):strptime("2009apr","%Y%b"),10000:]which is every invoice in the past year over 10,000 dollars. Expressing this without using an extended slice would require some cludgy pseudo-lazy slice intermediate value.
TokenMacGuy
I would tend to do something like SQLAlchemy does: create special "date" and "amount" column objects that, when compared with something, remember the comparison, and that let me say: invoices.where('2008apr' <= c.date < '2009apr').where(amount > 10000). Or, you could have less magic and just support: invoices.date_after('2008apr').date_before('2009apr').more_than(10000). But using slices would seem to violate the expectations of people reading Python code; that's not quite what they do. :-)
Brandon Craig Rhodes
A: 

From the docs:

There is ambiguity in the formal syntax here: anything that looks like an expression list also looks like a slice list, so any subscription can be interpreted as a slicing. Rather than further complicating the syntax, this is disambiguated by defining that in this case the interpretation as a subscription takes priority over the interpretation as a slicing (this is the case if the slice list contains no proper slice nor ellipses). Similarly, when the slice list has exactly one short slice and no trailing comma, the interpretation as a simple slicing takes priority over that as an extended slicing.

As such, I don't think it's possible to distinguish u[1,2]-as-extended-slice from u[1,2]-as-tuple-key.

John Fouhy
A: 

My current thinking about this is to simply let the types that normally associate with slices be uncollectable. I can't think of any sane reason why anyone would want to do anything with a slice value or Ellipsis except to use them in subscript expressions.

On the off chance a user of the collection wants to sort on a tuple (instead of numbers or strings or dates or any other obvious thing) It might make sense to just require some extra cruft. As the example...

>>> u[t]
<type 'tuple'> : (1, 2)
>>> u[t,]
<type 'tuple'> : ((1, 2),)

Haven't really tried it with actual code (don't actually have a working GiS index at this time) but i suspect that this might just automatically do the right thing, since the extended slice is a tuple of length one (one dimension), which happens to be a tuple.

TokenMacGuy