views:

404

answers:

3

Original question: Can someone tell me how to use "slice lists" and the "ellipsis"? When are they useful? Thanks.

Here's what the language definition says about "slice_list" and "ellipsis"; Alex Martelli's answer points out their origin, which is not what I had envisioned.

[http://docs.python.org/reference/expressions.html#tok-slicing%5D%5B1%5D

5.3.3. Slicings

extended_slicing ::= primary "[" slice_list "]"

slice_list ::= slice_item ("," slice_item)* [","]

slice_item ::= expression | proper_slice | ellipsis

ellipsis ::= "..."

[1]: http://docs.python.org/reference/expressions.html#tok-slicing

In case anyone (as I was) is looking for ways to attack a list (or a list of lists) with a list of slices, here are 5 ways to get a list of elements from a list that are selected by a list of slices and 2 ways to do the same thing to a list of lists, in that case applying one slice per list. The output's in a comment at the end. I find h5, the example that uses nested for loops, the hardest to understand if meaningful variable names aren't used (updated).

#!/usr/bin/env python



import itertools

puz = [(i + 100) for i in range(40)]
puz1 = list( puz)
puz2 = [(i + 200) for i in range(40)]
puz3 = [(i + 300) for i in range(40)]
puzs = [puz1,puz2,puz3]

sa = slice( 0,1,1)
sb = slice( 30,39,4)
sc = slice( -1, -15,-5)
ss = [sa,sb,sc]

def mapfunc( a,b):
    return a[b]

f = map( mapfunc,[puz] * len(ss),ss)
print "f =  ", f  #same as g below

g = [ puz[i]
    for i in ss ]
print "g =  ",g  #same as f, above

h1 = [ i 
    for i in itertools.chain( puz[sa],puz[sb],puz[sc]) ]
print "h1 = ", h1  #right 

h2 = [ i
    for i in itertools.chain( *(map( mapfunc,[puz] * len(ss),ss))) ]
print "h2 = ",h2  #right

h3 = [ i
    for i in itertools.chain( *f) ]
print "h3 = ",h3  #right

h4 = [ i 
    for i in itertools.chain( *g) ]
print "h4 = ", h4 #also right

h5 = []
for slice_object in ss:
    for list_element in puz[slice_object]:
        h5.append( list_element)
print "h5 = ", h5  #right, too

print "=============================="

hh1 = [ i
    for i in itertools.chain( *(map( mapfunc,puzs,ss))) ]
print "hh1 =  ",hh1  #right

puz_s_pairs = zip( puzs,ss)
#print "puz_s_pairs = ",puz_s_pairs
hh2 = [ i
    for i in itertools.chain( *(map( mapfunc,*zip( *puz_s_pairs)))) ]
print "hh2 =  ",hh2  #right

'''
>>> execfile(r'D:/cygwin/home/usr01/wrk/py/pyexpts/list_of_slices_of_list.02.py')
f =   [[100], [130, 134, 138], [139, 134, 129]]
g =   [[100], [130, 134, 138], [139, 134, 129]]
h1 =  [100, 130, 134, 138, 139, 134, 129]
h2 =  [100, 130, 134, 138, 139, 134, 129]
h3 =  [100, 130, 134, 138, 139, 134, 129]
h4 =  [100, 130, 134, 138, 139, 134, 129]
h5 =  [100, 130, 134, 138, 139, 134, 129]
==============================
hh1 =   [100, 230, 234, 238, 339, 334, 329]
hh2 =   [100, 230, 234, 238, 339, 334, 329]
'''
+1  A: 

Numpy uses them to implement array slicing.

Ned Batchelder
Ellipsis -- rarely used. Slicing -- common.
S.Lott
+5  A: 

Slice lists and ellipsis were originally introduced in Python to supply nice syntax sugar for the precedessor of numpy (good old Numeric). If you're using numpy (no reason to go back to any of its predecessors!-) you should of course use them; if for whatever strange reason you're doing your own implementation of super-flexible multi-dimensional arrays, you'll definitely want to study the way numpy uses them and probably imitate it closely (it is pretty well designed after all). I can't think of good uses beyond multi-dimensional arrays.

Alex Martelli
Ah. So I am not to think of "slicelists" as a way to winkle out arbitrary, multiple runs of lists in one compact expression, then. Pity. I almost had a use for that.
behindthefall
For "runs of lists" read "runs from a single, one-dimensional list".
behindthefall
@behindthefalls, no, runs are normally extracted with itertools.groupby -- no special syntax for that. You could of course implement such syntax in your own objects, not sure it would be all that readable to most people though.
Alex Martelli
Alex, thanks for the itertools.groupby tip: I've never noticed that operation, but I'll go look. I appreciate your help. I'm trying to understand code I wrote 4 years ago and am (hopefully) simplifying lots of list/set loops. It occurred to me that I could prepackage some things as slices or lists of slices --- if it was legal. Back to the drawing board.
behindthefall
itertools.groupby does something different, but there are a few ways to get lists of slices to work as expected. Poor list never knew what hit it. Now if I can get a list of slices to operate on a list of lists ..
behindthefall
Alex, I don't know if you'll see this, but I put some ways of applying a list of slices (not a slice_list) to a list or list of lists up in an addendum to the original question. Maybe someone will run across it and find it useful or amusing.
behindthefall
I do see all comments made on my answers -- and I do agree with your remark that better variable names would help, as the present one are quite confusing, though otherwise the code does seem useful.
Alex Martelli
OK -- that was a hanging thread with the h5 variable names; just improved them for didactic purposes. It's fun working through the various ways to select from lists.
behindthefall
Alex, I've put up a "def next()" question, if you'd be willing to post your solution to providing pre-2.6 Python with that function. Thanks.
behindthefall
+1  A: 

I'm not too sure about ellipsis, so I will not address that, lest I give you a bad answer.

Here goes list slicing:

I hope you know that list indeces begin at 0.

l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Indexing into a list:

l[0]
>>> 0

l[5]
>>> 5

Slicing a list. The first index is included, but not the last:

l[0:5]
>>> [0, 1, 2, 3, 4]

l[2:5]
>>> [2, 3, 4]

Return the whole list as ONE slice:

l[:]
>>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Get a slice of the list containing every element including and after the 3rd index:

l[3:]
>>> [3, 4, 5, 6, 7, 8, 9]

Get a slice of the list containing every element upto but not including the 5th index:

l[:5]
>>> [0, 1, 2, 3, 4]

Here is something that you would not expect python to do:

l[5:18]  # note: there is no 18th index in this list
>>> [5, 6, 7, 8, 9]
inspectorG4dget
Note that the l[:] option is a shorthand for copying the array and you'll see it fairly frequently.
Karl Guertin
It's when I run into the fact that the language allows you to have two or more slice expressions separated by commas that I get puzzled! ;-)
behindthefall