Slice operation changes

Robin Thomas robin.thomas at starmedia.net
Fri Mar 2 11:57:01 EST 2001


At 05:55 AM 3/2/01 +0000, Donn Cave wrote:

>The problem for me is that when we write ob[i:j], we clearly
>must have expected that ob is a sliceable sequence.  If it is
>instead a mapping, then the expression has no sensible meaning,
>so it's an error and ought to raise an exception.

Making slice objects comparable/hashable is at cross purposes with 
forbidding their use as dictionary keys. Guido endorsed the strict 
forbiddance of slice objects as dict keys; that patch is more 
straightforward than extending the slice objects' behavior.

Proposed 2.1 patch:

- no changes to slice object
- Slice objects are rejected as dict keys, just as lists and dicts
   are rejected; this rejection is only on setitem; getitem
   will just throw suitable KeyError as it does now
- fix exception values for built-in types like DictType for
   the operation dict[i:j,]; the exception value
   strips the tupleness and I dislike that inconsistency
- change things so that obj[:] passes slice(None,None,None)
   instead of slice(0, sys.maxint, None)
   to mapping getitem (sequence getslice behavior still uses
   (0, sys.maxint) as defaults)

The last item deserves a little explanation. From the language reference 5.3.3:

"The semantics for a simple slicing are as follows. The primary must 
evaluate to a sequence object. The lower and upper bound expressions, if 
present, must evaluate to plain integers; defaults are zero and the 
sys.maxint, respectively. If either bound is negative, the sequence's 
length is added to it. The slicing now selects all items with index k such 
that i <= k < j where i and j are the specified lower and upper bounds. 
This may be an empty sequence. It is not an error if i or j lie outside the 
range of valid indexes (such items don't exist so they aren't selected)."

[Thus for simple slicing, the default lower bound is 0 and the default 
higher bound is sys.maxint.]

"The semantics for an extended slicing are as follows. The primary must 
evaluate to a mapping object, and it is indexed with a key that is 
constructed from the slice list, as follows. If the slice list contains at 
least one comma, the key is a tuple containing the conversion of the slice 
items; otherwise, the conversion of the lone slice item is the key. The 
conversion of a slice item that is an expression is that expression. The 
conversion of an ellipsis slice item is the built-in Ellipsis object. The 
conversion of a proper slice is a slice object (see section 3.2) whose 
start, stop and step attributes are the values of the expressions given as 
lower bound, upper bound and stride, respectively, substituting None for 
missing expressions."

Thus for extended slicing, default values for start, stop, and step are 
always None. If obj[i:j] finds that obj is not a sliceable sequence, the 
fallback to mapping getitem is by nature an extended slicing operation, and 
thus should obey extended slicing rules. Thus:

 >>> d = {}
 >>> d[:]
Traceback (innermost last):
   File "<pyshell#1>", line 1, in ?
     d[:]
KeyError: slice(0, 2147483647, None)

is wrong. Instead it should be:

 >>> d = {}
 >>> d[:]
Traceback (innermost last):
   File "<pyshell#1>", line 1, in ?
     d[:]
KeyError: slice(None, None, None)

Think this is a trivial issue? It's not. The whole reason for extended 
slicing was to let the Numeric Python guys have richly expressive slice 
objects: a None value always has a different and important meaning than 
some imposed default like sys.maxint. Treating [:] as some magic integer 
range is the wrong behavior, and requires implementations to write 
special-case code to handle slice(0, sys.maxint, None) as slice(None, None, 
None).

So this suggested small change just enforces the rules in section 5.3.3.

I will need a vote of confidence from the Numeric Python gang. My searches 
of NumPy source turn up no breakage as a result of the change. David A? Anyone?

I'll be unavailable for all of next week. If I can find the time today, 
I'll put together the first draft of the patch, but then I'll need to hand 
it off to someone else. Volunteers? Donn?

One last note:

With the above patches to 2.1, extended slice handling is now consistent 
with the Language Reference. Any type wishing to implement extended slicing 
has complete freedom in how to interpret the extended slice object or 
tuple. Thus we're free to add extended slice support incrementally to 
built-in types and only in ways that make sense for the type.

For 2.2 or later, I would like to add extended slice handling to several 
built-in types. I'll make a PEP. Here's a quick example to start the wheels 
turning:

 >>> s = "abcdef"
 >>> s[1:2,3:,::-1,3,765,...]
"bdeffedbcadabcdef"

I've wanted this kind of behavior for a while. :)


--
Robin Thomas
Engineering
StarMedia Network, Inc.
robin.thomas at starmedia.net
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-list/attachments/20010302/c1058391/attachment.html>


More information about the Python-list mailing list